From dc3d0ab277dd374ff562b5e249a0078c8d442aed Mon Sep 17 00:00:00 2001 From: Artem Korsakov Date: Sat, 22 Mar 2025 09:50:58 +0300 Subject: [PATCH] Add personal tasks --- docs/images/personal_tasks.png | Bin 0 -> 49169 bytes docs/index.md | 14 ++++++++++++++ helpers/fetchProgress.ts | 18 +++++++++++------- helpers/parsers.ts | 2 +- helpers/progressBlock.ts | 26 ++++++++++++++++++++++++-- helpers/sourceExtractor.ts | 14 ++++++++++++++ helpers/types.ts | 13 +++++++++++++ main.ts | 4 +++- 8 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 docs/images/personal_tasks.png create mode 100644 helpers/sourceExtractor.ts diff --git a/docs/images/personal_tasks.png b/docs/images/personal_tasks.png new file mode 100644 index 0000000000000000000000000000000000000000..88777db3f04c4449ff6f3a8b1e9b0240214fdc8d GIT binary patch literal 49169 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md index cc31eef..446fc0a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -94,6 +94,20 @@ Here, you can see your current tasks and how many problems you need to solve to tasks +### Personal tasks + +You can add your personal tasks: + +```` +```euler-stats +Solve problem 3; 0% +Solve problem 14; 15.6% +Solve problem 15; 27.1% +``` +```` + +personal tasks + ### Location progress This section provides an overview of your ranking in the **Location rating** on Project Euler. diff --git a/helpers/fetchProgress.ts b/helpers/fetchProgress.ts index 9ceb943..b29479b 100644 --- a/helpers/fetchProgress.ts +++ b/helpers/fetchProgress.ts @@ -18,9 +18,11 @@ import { AccountData, AwardBlockData, FriendData, + LevelData, + PersonalTask, ProgressData, RatingData, - LevelData + Source } from './types'; const mainUrl = 'https://projecteuler.net/'; @@ -34,11 +36,11 @@ const keepAliveName = 'keep_alive'; * @param retries - The number of retries in case of failure. * @returns A Promise that resolves to an HTMLElement. */ -export async function fetchProgress(session: string, keep_alive: string): Promise { +export async function fetchProgress(session: string, keep_alive: string, source: Source): Promise { const cookies = `${sessionIdName}=${session}; ${keepAliveName}=${keep_alive}`; try { - return await tryToFetchProgress(cookies); + return await tryToFetchProgress(cookies, source); } catch (error) { console.error('Error fetching progress:', error); @@ -48,7 +50,7 @@ export async function fetchProgress(session: string, keep_alive: string): Promis } } -async function tryToFetchProgress(cookies: string): Promise { +async function tryToFetchProgress(cookies: string, source: Source): Promise { const [ accountData, progressData, @@ -78,7 +80,8 @@ async function tryToFetchProgress(cookies: string): Promise { languageRating, levelDataArray, awardsData, - friends + friends, + source ); } @@ -119,7 +122,8 @@ function generateHTML( languageRating: RatingData, levelDataArray: LevelData[], awardsData: AwardBlockData[], - friends: FriendData[] + friends: FriendData[], + source: Source ): HTMLElement { const container = document.createElement('div'); @@ -129,7 +133,7 @@ function generateHTML( const imageElement = generateImageHTML(accountData.account); container.appendChild(imageElement); - const progressElement = generateProgressTableHTML(accountData, progressData, locationUrl, languageUrl, euleriansPlace, locationRating, languageRating, awardsData); + const progressElement = generateProgressTableHTML(accountData, progressData, locationUrl, languageUrl, euleriansPlace, locationRating, languageRating, awardsData, source); container.appendChild(progressElement); const locationRatingElement = generateRatingTableHTML(locationUrl, accountData.location, progressData.solved, locationRating); diff --git a/helpers/parsers.ts b/helpers/parsers.ts index 5d87955..864da68 100644 --- a/helpers/parsers.ts +++ b/helpers/parsers.ts @@ -12,7 +12,7 @@ export function extractSolvedCount(text: string): number { return match && match[1] ? parseInt(match[1], 10) : 0; } -function extractPercentage(input: string): number { +export function extractPercentage(input: string): number { const regex = /(\d+(\.\d+)?)%/; const match = input.match(regex); diff --git a/helpers/progressBlock.ts b/helpers/progressBlock.ts index ed00e55..dd4312b 100644 --- a/helpers/progressBlock.ts +++ b/helpers/progressBlock.ts @@ -1,4 +1,4 @@ -import { AccountData, AwardData, AwardBlockData, ProgressData, RatingData } from './types'; +import { AccountData, AwardData, AwardBlockData, PersonalTask, ProgressData, RatingData, Source } from './types'; import { createProgressBar, createSectionHeader } from './commonBlocks'; interface Result { @@ -140,6 +140,20 @@ function createProgressTable( return table; } +function createPersonalTasksList(personalTasks: PersonalTask[]): HTMLElement { + const tasksList = document.createElement('ul'); + tasksList.className = 'tasks-list'; + + personalTasks.forEach(personalTask => { + const li = document.createElement('li'); + li.textContent = personalTask.task; + li.appendChild(createProgressBar(personalTask.percentage)); + tasksList.appendChild(li); + }); + + return tasksList; +} + function createTasksList( progressData: ProgressData, accountData: AccountData, @@ -200,6 +214,7 @@ function createTasksList( * @param locationRating - The location rating data. * @param languageRating - The language rating data. * @param awardsData - The awards data. + * @param source - The source data. * @returns The generated HTMLElement (progress table container). */ export function generateProgressTableHTML( @@ -210,7 +225,8 @@ export function generateProgressTableHTML( euleriansPlace: string, locationRating: RatingData, languageRating: RatingData, - awardsData: AwardBlockData[] + awardsData: AwardBlockData[], + source: Source ): HTMLElement { const progressContainer = document.createElement('div'); progressContainer.appendChild(createSectionHeader('Progress')); @@ -225,6 +241,12 @@ export function generateProgressTableHTML( languageRating )); + // Personal tasks section + const personalTasksHeader = document.createElement('h3'); + personalTasksHeader.textContent = 'Personal tasks'; + progressContainer.appendChild(personalTasksHeader); + progressContainer.appendChild(createPersonalTasksList(source.tasks)); + // Tasks section const tasksHeader = document.createElement('h3'); tasksHeader.textContent = 'Tasks'; diff --git a/helpers/sourceExtractor.ts b/helpers/sourceExtractor.ts new file mode 100644 index 0000000..5d01e03 --- /dev/null +++ b/helpers/sourceExtractor.ts @@ -0,0 +1,14 @@ +import { Source, PersonalTask } from './types'; +import { extractPercentage } from './parsers'; + +export function extractSources(source: string): Source { + const tasks = source + .split('\n') + .filter(line => line.trim() !== '') + .map(line => { + const [task, percentage] = line.split(';').map(part => part.trim()); + return new PersonalTask(task, extractPercentage(percentage)); + }); + + return new Source(tasks); +} diff --git a/helpers/types.ts b/helpers/types.ts index 3bcd13a..6ceb73e 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -110,3 +110,16 @@ export class FriendData { public awards: number ) {} } + +export class Source { + constructor( + public tasks: PersonalTask[], + ) {} +} + +export class PersonalTask { + constructor( + public task: string, + public percentage: number + ) {} +} diff --git a/main.ts b/main.ts index 4858748..081297a 100644 --- a/main.ts +++ b/main.ts @@ -1,5 +1,6 @@ import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; import { fetchProgress } from "helpers/fetchProgress"; +import { extractSources } from "helpers/sourceExtractor"; export default class ProjectEulerStatsPlugin extends Plugin { settings: ProjectEulerStatsSettings; @@ -13,7 +14,8 @@ export default class ProjectEulerStatsPlugin extends Plugin { const keep_alive = this.settings.keep_alive; this.registerMarkdownCodeBlockProcessor('euler-stats', async (source, el, ctx) => { - const stats = await fetchProgress(session, keep_alive); + const extractedSource = extractSources(source); + const stats = await fetchProgress(session, keep_alive, extractedSource); const container = el.createEl('div'); container.appendChild(stats); });