From 8b3bb9c382bf444cbaf1b5103fe5291495839f89 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 25 Mar 2024 12:33:31 +0100 Subject: [PATCH] pfes --- pfes/sort/api.ts | 38 +++++++++++++++++++++++++++ pfes/sort/converter.ts | 58 ++++++++++++++++++++++++++++++++++++++++++ pfes/sort/input.csv | 25 ------------------ pfes/sort/main.ts | 49 ----------------------------------- pfes/sort/output.csv | 6 ----- pfes/sort/utils.ts | 23 +++++++++++++++++ 6 files changed, 119 insertions(+), 80 deletions(-) create mode 100755 pfes/sort/api.ts create mode 100755 pfes/sort/converter.ts delete mode 100644 pfes/sort/input.csv delete mode 100755 pfes/sort/main.ts delete mode 100644 pfes/sort/output.csv create mode 100644 pfes/sort/utils.ts diff --git a/pfes/sort/api.ts b/pfes/sort/api.ts new file mode 100755 index 0000000..16f28ee --- /dev/null +++ b/pfes/sort/api.ts @@ -0,0 +1,38 @@ +#!/bin/env -S deno run -A + +import { group_inputs, members_from_cells, Memeber, write_to_csv } from "./converter.ts"; +import { enumerate } from "./utils.ts"; + +async function main() { + const sheet_id = "il9cnn4s9ugc"; + const sheet = await get_sheet(sheet_id); + const members = extract_members(sheet, [0, 4]); + const groups = group_inputs(members, 4); + await write_to_csv("./output.csv", groups); +} + +type Sheet = Awaited>; +async function get_sheet(sheet_id: string) { + const response = await fetch(`https://ethercalc.net/${sheet_id}.csv`); + const body = await response.text(); + return body.split("\n").map((line) => line.split(",")); +} + +function extract_members(sheet: Sheet, input_top_left: coords): Memeber[] { + const [tl_x, tl_y] = input_top_left; + const filtered = [] as string[][]; + for (const [y, line] of enumerate(sheet)) { + if (y < tl_y) continue; + const filtered_line = [] as string[]; + for (const [x, cell] of enumerate(line)) { + if (x < tl_x) continue; + filtered_line.push(cell); + } + filtered.push(filtered_line); + } + return members_from_cells(filtered); +} + +type coords = [number, number]; + +if (import.meta.main) await main(); diff --git a/pfes/sort/converter.ts b/pfes/sort/converter.ts new file mode 100755 index 0000000..ff38289 --- /dev/null +++ b/pfes/sort/converter.ts @@ -0,0 +1,58 @@ +#!/bin/env -S deno run -A + +import { enumerate, range, to_int } from "./utils.ts"; + +function main() { + const max_in_group = 4; + const input = read_input("./input.csv"); + const groups = group_inputs(input, max_in_group); + write_to_csv("./output.csv", groups); +} + +function read_input(path: string) { + const content = Deno.readTextFileSync(path); + const cells = content.split("\n").filter((line) => line !== "").map((line) => line.split("\t")); + const result = members_from_cells(cells); + return result; +} + +export type Memeber = ReturnType[0]; +export function members_from_cells(cells: string[][]) { + return cells.map(( + [login, s1, s2, s3, s4, s5, s6], + ) => ({ login, choices: ([s1, s2, s3, s4, s5, s6] as const).map(to_int), placed: false })); +} + +export type Group = ReturnType[0]; +export function group_inputs(input: Memeber[], max_in_group: number) { + const groups = range(1, 7) + .arr() + .map((sujet_no) => ({ sujet_no, members: [] as { login: string; prio: number }[] })); + + for (const prio of range(1, 7)) { + for (const entry of input) { + if (entry.placed) continue; + for (const [index, choice] of enumerate(entry.choices)) { + if (choice !== prio) continue; + if (groups[index].members.length >= max_in_group) continue; + groups[index].members.push({ login: entry.login, prio }); + entry.placed = true; + } + } + } + return groups; +} + +export function groups_to_cells(groups: Group[]) { + return groups.map(({ sujet_no, members }) => [ + `Sujet ${sujet_no}`, + ...members.map(({ login, prio }) => `${prio} ${login}`), + ]); +} + +export function write_to_csv(path: string, groups: Group[]) { + const result = groups_to_cells(groups).map((line) => line.join("\t")).join("\n"); + Deno.writeTextFileSync(path, result); +} + +if (import.meta.main) main(); diff --git a/pfes/sort/input.csv b/pfes/sort/input.csv deleted file mode 100644 index a8e2d8c..0000000 --- a/pfes/sort/input.csv +++ /dev/null @@ -1,25 +0,0 @@ -alexandre.di-santo -anas.el-khatir 2 5 3 1 4 6 -arnaud.avare -baptiste.mabille -bastien.taur -clement.thollet 2 6 3 1 5 4 -edwin.galibert 1 2 6 5 3 4 -enzo.laik -julia.royer 5 4 1 2 6 3 -loick.balloy -luna.zozor 4 5 1 2 6 3 -matthieu.jolimaitre 6 1 5 4 2 3 -nicolas.bruguet 3 4 2 1 6 5 -nicolas.marc 4 3 2 1 6 5 -noe.bigorre -quentin.de-capele -theo.dedaele 1 2 4 3 6 5 -theo.loret -thomas.didier -valentin.champenois -valentin.giaufer 5 4 3 1 6 2 -vincent.goguyer-lalande 3 5 2 1 6 4 -vincent.guillen -yann.goulvestre 2 6 3 1 5 4 -yannis.breleur 4 5 3 1 6 2 diff --git a/pfes/sort/main.ts b/pfes/sort/main.ts deleted file mode 100755 index 47d8153..0000000 --- a/pfes/sort/main.ts +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/env -S deno run -A - -function main() { - const input = read_input("./input.csv"); - - const MAX_IN_GROUP = 4; - const groups = Array.from(range(1, 7)) - .map((sujet_no) => ({ sujet_no, members: [] as { login: string; prio: number }[] })); - - for (const prio of range(1, 7)) { - for (const entry of input) { - if (entry.placed) continue; - for (const [index, choice] of enumerate(entry.choices)) { - if (choice !== prio) continue; - if (groups[index].members.length >= MAX_IN_GROUP) continue; - groups[index].members.push({ login: entry.login, prio }); - entry.placed = true; - } - } - } - - let result = ""; - for (const group of groups) { - const members = group.members.map((item) => `${item.login}(${item.prio})`).join("\t"); - const line = `Sujet ${group.sujet_no}\t${members}`; - result += line + "\n"; - } - Deno.writeTextFileSync("./output.csv", result); -} - -function read_input(path: string) { - const content = Deno.readTextFileSync(path); - const cells = content.split("\n").filter((line) => line !== "").map((line) => line.split("\t")); - const toint = (n: string) => ((parsed) => isNaN(parsed) ? 0 : parsed)(parseInt(n)); - return cells.map(( - [login, s1, s2, s3, s4, s5, s6], - ) => ({ login, choices: ([s1, s2, s3, s4, s5, s6] as const).map(toint), placed: false })); -} - -function* range(from: number, to: number) { - while (from < to) yield from++; -} - -function* enumerate(iterable: Iterable) { - let index = 0; - for (const item of iterable) yield [index++, item] as const; -} - -if (import.meta.main) main(); diff --git a/pfes/sort/output.csv b/pfes/sort/output.csv deleted file mode 100644 index 4013edb..0000000 --- a/pfes/sort/output.csv +++ /dev/null @@ -1,6 +0,0 @@ -Sujet 1 edwin.galibert(1) theo.dedaele(1) yann.goulvestre(2) -Sujet 2 matthieu.jolimaitre(1) -Sujet 3 julia.royer(1) luna.zozor(1) vincent.goguyer-lalande(2) -Sujet 4 anas.el-khatir(1) clement.thollet(1) nicolas.bruguet(1) nicolas.marc(1) -Sujet 5 -Sujet 6 valentin.giaufer(2) yannis.breleur(2) diff --git a/pfes/sort/utils.ts b/pfes/sort/utils.ts new file mode 100644 index 0000000..2743ee2 --- /dev/null +++ b/pfes/sort/utils.ts @@ -0,0 +1,23 @@ +export const to_int = (n: string) => ((parsed) => isNaN(parsed) ? 0 : parsed)(parseInt(n)); + +export function range(from: number, to: number) { + function* gen() { + while (from < to) yield from++; + } + return iterable_to_arrayable(gen()); +} + +export function enumerate(iterable: Iterable) { + function* gen() { + let index = 0; + for (const item of iterable) yield [index++, item] as const; + } + return iterable_to_arrayable(gen()); +} + +function iterable_to_arrayable(iterator: Iterable) { + // deno-lint-ignore no-explicit-any + const anyfied = iterator as any; + anyfied.arr = () => Array.from(iterator); + return anyfied as Iterable & { arr: () => T[] }; +}