Created
July 26, 2026 11:23
-
-
Save bxt/1ffef09f65097769b9938a4e2239d77b to your computer and use it in GitHub Desktop.
Moonpie progeess bars
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { describe, expect, test } from "vitest"; | |
| import { moonPieProgress } from "./moonPieProgress.ts"; | |
| describe("moonPieProgress", () => { | |
| test("for for length 4", () => { | |
| expect.soft(moonPieProgress(0, 4)).toBe("π"); | |
| expect.soft(moonPieProgress(1, 4)).toBe("π"); | |
| expect.soft(moonPieProgress(2, 4)).toBe("π"); | |
| expect.soft(moonPieProgress(3, 4)).toBe("π"); | |
| expect.soft(moonPieProgress(4, 4)).toBe("π"); | |
| }); | |
| test("for for length 12", () => { | |
| expect.soft(moonPieProgress(0, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(1, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(2, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(3, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(4, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(5, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(6, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(7, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(8, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(9, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(10, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(11, 12)).toBe("πππ"); | |
| expect.soft(moonPieProgress(12, 12)).toBe("πππ"); | |
| }); | |
| test("for for length 0", () => { | |
| expect.soft(moonPieProgress(0, 0)).toBe(""); | |
| }); | |
| test("for for length 1", () => { | |
| expect.soft(moonPieProgress(0, 1)).toBe("π"); | |
| expect.soft(moonPieProgress(1, 1)).toBe("π"); | |
| }); | |
| test("for for length 2", () => { | |
| expect.soft(moonPieProgress(0, 2)).toBe("π"); | |
| expect.soft(moonPieProgress(1, 2)).toBe("π"); | |
| expect.soft(moonPieProgress(2, 2)).toBe("π"); | |
| }); | |
| test("for for length 3", () => { | |
| expect.soft(moonPieProgress(0, 3)).toBe("π"); | |
| expect.soft(moonPieProgress(1, 3)).toBe("π"); | |
| expect.soft(moonPieProgress(2, 3)).toBe("π"); | |
| expect.soft(moonPieProgress(3, 3)).toBe("π"); | |
| }); | |
| test("for for length 7", () => { | |
| expect.soft(moonPieProgress(0, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(1, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(2, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(3, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(4, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(5, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(6, 7)).toBe("ππ"); | |
| expect.soft(moonPieProgress(7, 7)).toBe("ππ"); | |
| }); | |
| describe("throws when values are out of range #bringYourOwnClamp", () => { | |
| test("does not accept negative progress", () => { | |
| expect(() => { | |
| moonPieProgress(-1, 12); | |
| }).toThrow(RangeError); | |
| }); | |
| test("does not accept progress overflow", () => { | |
| expect(() => { | |
| moonPieProgress(13, 12); | |
| }).toThrow(RangeError); | |
| }); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const lunaCodePoint = 0x25 * 0b11 * 11_51; | |
| const phases = 4; | |
| const emptyString = String.fromCodePoint(lunaCodePoint); | |
| const filledString = String.fromCodePoint(lunaCodePoint + 4); | |
| /** | |
| * Displays a progress bar using moon emojis. | |
| * @param i Progress value, between 0 and `length` inclusive | |
| * @param length Maximum progress value | |
| * @throws `RangeError` For out of range progress values `i` | |
| * @returns A string like "πππ" | |
| */ | |
| export function moonPieProgress(i: number, length: number): string { | |
| const total = Math.ceil(length / phases); | |
| const filled = Math.floor(i / phases); | |
| const filledStrings = filledString.repeat(filled); | |
| const phase = i % phases; | |
| if (phase === 0) return filledStrings + emptyString.repeat(total - filled); | |
| const codePointOffset = (8 - phase) % 8; | |
| const phaseString = String.fromCodePoint(lunaCodePoint + codePointOffset); | |
| return filledStrings + phaseString + emptyString.repeat(total - filled - 1); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment