mirror of
https://github.com/artemkorsakov/project-euler-stats.git
synced 2026-07-22 05:42:55 +00:00
Add personal tasks
This commit is contained in:
parent
2de9245e28
commit
dc3d0ab277
8 changed files with 80 additions and 11 deletions
BIN
docs/images/personal_tasks.png
Normal file
BIN
docs/images/personal_tasks.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
|
|
@ -94,6 +94,20 @@ Here, you can see your current tasks and how many problems you need to solve to
|
|||
|
||||
<img src="images/tasks.png" alt="tasks" width="500" />
|
||||
|
||||
### Personal tasks
|
||||
|
||||
You can add your personal tasks:
|
||||
|
||||
````
|
||||
```euler-stats
|
||||
Solve problem 3; 0%
|
||||
Solve problem 14; 15.6%
|
||||
Solve problem 15; 27.1%
|
||||
```
|
||||
````
|
||||
|
||||
<img src="images/personal_tasks.png" alt="personal tasks" width="500" />
|
||||
|
||||
### Location progress
|
||||
|
||||
This section provides an overview of your ranking in the **Location rating** on Project Euler.
|
||||
|
|
|
|||
|
|
@ -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<HTMLElement> {
|
||||
export async function fetchProgress(session: string, keep_alive: string, source: Source): Promise<HTMLElement> {
|
||||
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<HTMLElement> {
|
||||
async function tryToFetchProgress(cookies: string, source: Source): Promise<HTMLElement> {
|
||||
const [
|
||||
accountData,
|
||||
progressData,
|
||||
|
|
@ -78,7 +80,8 @@ async function tryToFetchProgress(cookies: string): Promise<HTMLElement> {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
14
helpers/sourceExtractor.ts
Normal file
14
helpers/sourceExtractor.ts
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
) {}
|
||||
}
|
||||
|
|
|
|||
4
main.ts
4
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);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue