From 580e69a0d74ab60da778bdec5ee929eaf422b479 Mon Sep 17 00:00:00 2001 From: Thomas Cicognani Date: Thu, 26 Dec 2024 23:36:38 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20remove=20pick=20priority?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +- src/picker/service/PickerService.ts | 36 +-- test/main.test.ts | 22 +- test/picker/service/PickerService.test.ts | 288 +++++----------------- test/publish.test.ts | 29 ++- 5 files changed, 118 insertions(+), 270 deletions(-) diff --git a/README.md b/README.md index e820d40..84e63a5 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,10 @@ How To UseContributingCredits • + AuthorsLicense • - Projects using autophoto + Projects using autophoto • + Changelog

![bluesky](doc/bluesky-post.webp) @@ -26,7 +28,7 @@ * Pre-scan your directory for photos - Photos are detected by a path pattern - - Check all detected photos if they are valid + - Check all detected photos if they are valid (for instance BlueSky has size limitations) * Scan your directory for photos - For now only suppose to work with video game screenshots - Photos are detected by a path pattern @@ -246,3 +248,10 @@ the domains, the performance, etc. So, if you want to help me, I will be happy t > [zhykos.fr](https://www.zhykos.fr)  ·  > GitHub [@zhykos](https://github.com/Zhykos)  ·  > Bluesky [@zhykos](https://bsky.app/profile/zhykos.bsky.social) + +--- + +## Changelog + +* 2.1 + - Remove the pick priority of directories which have at least 4 photos to publish diff --git a/src/picker/service/PickerService.ts b/src/picker/service/PickerService.ts index dbc5c5b..fba269b 100644 --- a/src/picker/service/PickerService.ts +++ b/src/picker/service/PickerService.ts @@ -24,28 +24,7 @@ export class PickerService { return undefined; } - const possibilitiesPriority: UnpublishedVideoGamesScreenshot[] = - unpublishedVideoGamesScreenshots.filter( - (screenshot) => screenshot.images.length >= 4, - ); - - if (possibilitiesPriority.length > 0) { - return this.pickScreenshotsToShare(possibilitiesPriority); - } - - const mapByLength = new Map(); - for (const screenshot of unpublishedVideoGamesScreenshots) { - const length: number = screenshot.images.length; - if (!mapByLength.has(length)) { - mapByLength.set(length, []); - } - mapByLength.get(length)?.push(screenshot); - } - return this.pickScreenshotsToShare( - mapByLength.get(3) ?? - mapByLength.get(2) ?? - (mapByLength.get(1) as UnpublishedVideoGamesScreenshot[]), - ); + return this.pickScreenshotsToShare(unpublishedVideoGamesScreenshots); } private pickScreenshotsToShare( @@ -67,18 +46,19 @@ export class PickerService { private async getUnpublishedVideoGamesScreenshots(): Promise< UnpublishedVideoGamesScreenshot[] > { - const unpublishedScreenshotRelations: UnpublishedVideoGameScreenshotRelation[] = - await this.relationRepository.getUnpublishedVideoGameRelations(); + const unpublishedScreenshotRelations: + UnpublishedVideoGameScreenshotRelation[] = await this.relationRepository + .getUnpublishedVideoGameRelations(); const unpublishedVideoGamesIDs: string[] = distinct( unpublishedScreenshotRelations.map((rel) => rel.videoGameID), ); - const unpublishedVideoGames: VideoGame[] = - await this.videoGameRepository.getVideoGames(unpublishedVideoGamesIDs); + const unpublishedVideoGames: VideoGame[] = await this.videoGameRepository + .getVideoGames(unpublishedVideoGamesIDs); const unpublishedImagesIDs: string[] = distinct( unpublishedScreenshotRelations.map((rel) => rel.imageID), ); - const unpublishedImages: Image[] = - await this.imageRepository.getVideoGameScreenshots(unpublishedImagesIDs); + const unpublishedImages: Image[] = await this.imageRepository + .getVideoGameScreenshots(unpublishedImagesIDs); return UnpublishedVideoGamesScreenshot.buildAll( unpublishedScreenshotRelations, unpublishedVideoGames, diff --git a/test/main.test.ts b/test/main.test.ts index 3e8d32d..ec72a38 100644 --- a/test/main.test.ts +++ b/test/main.test.ts @@ -1,5 +1,9 @@ -import { assertEquals } from "@std/assert"; -import { assertNotEquals } from "@std/assert/not-equals"; +import { + assert, + assertEquals, + assertMatch, + assertNotEquals, +} from "@std/assert"; import { afterAll, beforeAll, @@ -78,14 +82,14 @@ describe("main", () => { ]); assertNotEquals(mockedBlueskyServer.lastRecord, undefined); - assertEquals( - mockedBlueskyServer.lastRecord?.text, - 'Screenshots from video game "80\'s Overdrive" (2017) taken on Nintendo Switch', + assertMatch( + mockedBlueskyServer.lastRecord?.text ?? "", + /^Screenshots? from video game ".+" \(\d+\) taken on .+$/, ); - assertEquals(mockedBlueskyServer.lastRecord?.embed.images.length, 4); - assertEquals( - mockedBlueskyServer.lastRecord?.embed.images[0].alt, - "Screenshot from video game 80's Overdrive (no more details given by the bot)", + assert((mockedBlueskyServer.lastRecord?.embed.images.length ?? 0) > 0); + assertMatch( + mockedBlueskyServer.lastRecord?.embed.images[0].alt ?? "", + /^Screenshot from video game .+ \(no more details given by the bot\)$/, ); assertNotEquals( mockedBlueskyServer.lastRecord?.embed.images[0].image, diff --git a/test/picker/service/PickerService.test.ts b/test/picker/service/PickerService.test.ts index 8fdc1dc..9ae81d0 100644 --- a/test/picker/service/PickerService.test.ts +++ b/test/picker/service/PickerService.test.ts @@ -1,5 +1,5 @@ -import { assert, assertEquals, assertNotEquals } from "@std/assert"; -import { distinct, withoutAll } from "@std/collections"; +import { assertEquals } from "@std/assert"; +import { distinct } from "@std/collections"; import { beforeEach, describe, it } from "@std/testing/bdd"; import { KvDriver } from "../../../src/common/dbdriver/KvDriver.ts"; import type { ImageRepositoryRepositoryEntity } from "../../../src/common/repository/entity/ImageRepositoryRepositoryEntity.ts"; @@ -89,7 +89,7 @@ describe("PickerService", () => { }); }); -async function pickEveryPhotos() { +async function pickEveryPhotos(): Promise { const filesAfterScan: ImageRepositoryRepositoryEntity[] = await getAllImagesFromRepository(tempDatabaseFilePath); filesAfterScan.sort((a, b) => a.path.localeCompare(b.path)); @@ -113,8 +113,8 @@ async function pickEveryPhotos() { const bayonetta: VideoGameRepositoryEntity = videoGamesAfterScan.find( (vg) => vg.title === "8-Bit Bayonetta", ) as VideoGameRepositoryEntity; - const bayonettaLinks: VideoGameRelationImageRepositoryEntity[] = - allLinks.filter((link) => link.videoGameID === bayonetta.uuid); + const bayonettaLinks: VideoGameRelationImageRepositoryEntity[] = allLinks + .filter((link) => link.videoGameID === bayonetta.uuid); assertEquals(bayonettaLinks.length, 2); assertEquals(distinct(bayonettaLinks.map((l) => l.platform)), ["PC"]); @@ -123,8 +123,8 @@ async function pickEveryPhotos() { const overdrive: VideoGameRepositoryEntity = videoGamesAfterScan.find( (vg) => vg.title === "80's Overdrive", ) as VideoGameRepositoryEntity; - const overdriveLinks: VideoGameRelationImageRepositoryEntity[] = - allLinks.filter((link) => link.videoGameID === overdrive.uuid); + const overdriveLinks: VideoGameRelationImageRepositoryEntity[] = allLinks + .filter((link) => link.videoGameID === overdrive.uuid); assertEquals(overdriveLinks.map((l) => l.platform).sort(), [ "Nintendo Switch", "Nintendo Switch", @@ -137,8 +137,8 @@ async function pickEveryPhotos() { const absolver: VideoGameRepositoryEntity = videoGamesAfterScan.find( (vg) => vg.title === "Absolver", ) as VideoGameRepositoryEntity; - const absolverLinks: VideoGameRelationImageRepositoryEntity[] = - allLinks.filter((link) => link.videoGameID === absolver.uuid); + const absolverLinks: VideoGameRelationImageRepositoryEntity[] = allLinks + .filter((link) => link.videoGameID === absolver.uuid); assertEquals(absolverLinks.length, 1); assertEquals( absolverLinks.map((l) => l.platform), @@ -149,27 +149,15 @@ async function pickEveryPhotos() { const control: VideoGameRepositoryEntity = videoGamesAfterScan.find( (vg) => vg.title === "Control", ) as VideoGameRepositoryEntity; - const controlLinks: VideoGameRelationImageRepositoryEntity[] = - allLinks.filter((link) => link.videoGameID === control.uuid); + const controlLinks: VideoGameRelationImageRepositoryEntity[] = allLinks + .filter((link) => link.videoGameID === control.uuid); assertEquals(controlLinks.length, 5); assertEquals(distinct(controlLinks.map((l) => l.platform)), ["PC"]); // ============= Check picker =================================== - // ============= 1) and 2) 4/5 images for Control on PC ========= - // ============= OR 4/4 images for 80's Overdrive on Switch ===== - // ============= 3) 2/2 images for 8-Bit Bayonetta on PC ======== - // ============= 4) 1/1 remaining image for Control on PC ====== - // ============= 4) OR 1/1 image for 80's Overdrive on PC ======= - // ============= 4) OR 1/1 image for Absolver on PC ============= - // ============= 5) and 6) Randomly chose remaining images ====== - // ============= 13 images in total ============================= - // Get all video games with at least 4 images to share + // Get all video games with at least 1 image to share // Randomly pick one of them // Repeat - // If no video game with at least 4 images to share, get other video games - // Sort by number of images to share, take the one with the most images to share - // If equal, randomly pick one - // Repeat const kvDriver = new KvDriver(tempDatabaseFilePath); @@ -180,217 +168,73 @@ async function pickEveryPhotos() { new KvImageRepository(kvDriver), ); - const unusedControlImage: VideoGameRelationImageRepositoryEntity = - await pick1And2(pickerService, overdriveLinks, controlLinks); - await pick3Bayonetta(pickerService, bayonettaLinks); - await pick4and5and6( - pickerService, - overdriveLinks.find( - (l) => l.platform === "PC", - ) as VideoGameRelationImageRepositoryEntity, - absolverLinks[0], - unusedControlImage, - ); - - assertEquals(await pickerService.pick(), undefined); - } finally { - kvDriver.close(); - } -} - -async function pick1And2( - pickerService: PickerService, - allOverdriveLinks: VideoGameRelationImageRepositoryEntity[], - controlLinks: VideoGameRelationImageRepositoryEntity[], -): Promise { - const possibleTitles = ["80's Overdrive", "Control"]; - const overdriveLinks: VideoGameRelationImageRepositoryEntity[] = - allOverdriveLinks.filter((l) => l.platform === "Nintendo Switch"); - - assertEquals(overdriveLinks.length, 4); - assertEquals(controlLinks.length, 5); - - const screenshotsPick1: VideoGameScreeshotsToShare = - (await pickerService.pick()) as VideoGameScreeshotsToShare; - assertEquals(screenshotsPick1.screenshots.length, 4); - - const pick1index: number = possibleTitles.indexOf(screenshotsPick1.title); - assert(pick1index >= 0); - - let unusedControlImage: VideoGameRelationImageRepositoryEntity | undefined = - undefined; + let pick: VideoGameScreeshotsToShare | undefined = await pickerService + .pick(); - if (pick1index === 0) { - await pickOverdriveSwitch(overdriveLinks, screenshotsPick1); - possibleTitles.splice(0, 1); - } else { - unusedControlImage = await pickControl(controlLinks, screenshotsPick1); - possibleTitles.splice(1, 1); - } - - const screenshotsPick2: VideoGameScreeshotsToShare = - (await pickerService.pick()) as VideoGameScreeshotsToShare; - assertEquals(screenshotsPick2.screenshots.length, 4); - assertEquals(screenshotsPick2.title, possibleTitles[0]); - - if (pick1index === 0) { - unusedControlImage = await pickControl(controlLinks, screenshotsPick2); - } else { - await pickOverdriveSwitch(overdriveLinks, screenshotsPick2); - } - - return unusedControlImage as VideoGameRelationImageRepositoryEntity; -} - -async function pickOverdriveSwitch( - possibleLinksImageIDs: VideoGameRelationImageRepositoryEntity[], - pick: VideoGameScreeshotsToShare, -): Promise { - console.log("80s Overdrive Switch picked"); - - assertEquals( - pick.screenshots.map((s) => s.id).sort(), - possibleLinksImageIDs.map((l) => l.imageID).sort(), - ); - assertEquals(pick.platform, "Nintendo Switch"); - assertEquals(pick.title, "80's Overdrive"); - - await publishLinks(possibleLinksImageIDs); -} + const allPickedImagesNumber: number[] = []; + const allPickedImagesIDs: string[] = []; + const allPickedPlatforms: string[] = []; + const allPickedTitles: string[] = []; -async function pickControl( - possibleLinksImageIDs: VideoGameRelationImageRepositoryEntity[], - pick: VideoGameScreeshotsToShare, -): Promise { - console.log("Control picked"); + while (pick) { + const screenshotsToShare = pick as VideoGameScreeshotsToShare; + allPickedImagesNumber.push(screenshotsToShare.screenshots.length); - const notUsedImageIds: string[] = withoutAll( - possibleLinksImageIDs.map((l) => l.imageID), - pick.screenshots.map((l) => l.id), - ); - - assertEquals(notUsedImageIds.length, 1); - assert( - possibleLinksImageIDs.map((l) => l.imageID).includes(notUsedImageIds[0]), - ); - - assertEquals(pick.platform, "PC"); - assertEquals(pick.title, "Control"); + const allImagesIDs: string[] = screenshotsToShare.screenshots.map( + (f) => f.id, + ); + allPickedImagesIDs.push(...allImagesIDs); - const linksToPublish: VideoGameRelationImageRepositoryEntity[] = - possibleLinksImageIDs.filter((l) => l.imageID !== notUsedImageIds[0]); - assertEquals(linksToPublish.length, 4); + allPickedPlatforms.push(screenshotsToShare.platform); + allPickedTitles.push(screenshotsToShare.title); - await publishLinks(linksToPublish); + let linksToPublish: VideoGameRelationImageRepositoryEntity[] = []; - return possibleLinksImageIDs.find( - (l) => l.imageID === notUsedImageIds[0], - ) as VideoGameRelationImageRepositoryEntity; -} + if (screenshotsToShare.title === "8-Bit Bayonetta") { + linksToPublish = bayonettaLinks; + } else if (screenshotsToShare.title === "80's Overdrive") { + linksToPublish = overdriveLinks; + } else if (screenshotsToShare.title === "Absolver") { + linksToPublish = absolverLinks; + } else if (screenshotsToShare.title === "Control") { + linksToPublish = controlLinks; + } -async function pick3Bayonetta( - pickerService: PickerService, - bayonettaLinks: VideoGameRelationImageRepositoryEntity[], -): Promise { - const screenshotsBayonetta: VideoGameScreeshotsToShare = - (await pickerService.pick()) as VideoGameScreeshotsToShare; - assertEquals(screenshotsBayonetta.screenshots.length, 2); - assertEquals( - screenshotsBayonetta.screenshots.map((f) => f.id).sort(), - bayonettaLinks.map((l) => l.imageID).sort(), - ); - assertEquals(screenshotsBayonetta.platform, "PC"); - assertEquals(screenshotsBayonetta.title, "8-Bit Bayonetta"); - await publishLinks(bayonettaLinks); -} + await publishLinks( + linksToPublish.filter((l) => allImagesIDs.includes(l.imageID)), + ); -async function pick4and5and6( - pickerService: PickerService, - overdriveLink: VideoGameRelationImageRepositoryEntity, - absolverLink: VideoGameRelationImageRepositoryEntity, - controlLink: VideoGameRelationImageRepositoryEntity, -) { - const possibleTitles = ["80's Overdrive", "Absolver", "Control"]; - - const screenshotsPick4: VideoGameScreeshotsToShare = - (await pickerService.pick()) as VideoGameScreeshotsToShare; - const pick4index: number = possibleTitles.indexOf(screenshotsPick4.title); - assert(pick4index >= 0); - - if (pick4index === 0) { - await pickOverdrivePC(overdriveLink, screenshotsPick4); - } else if (pick4index === 1) { - await pickAbsolver(absolverLink, screenshotsPick4); - } else { - await pickRemainingControl(controlLink, screenshotsPick4); - } + pick = await pickerService.pick(); + } - const screenshotsPick5: VideoGameScreeshotsToShare = - (await pickerService.pick()) as VideoGameScreeshotsToShare; - const pick5index: number = possibleTitles.indexOf(screenshotsPick5.title); - assert(pick5index >= 0); - assertNotEquals(pick5index, pick4index); - - if (pick5index === 0) { - await pickOverdrivePC(overdriveLink, screenshotsPick5); - } else if (pick5index === 1) { - await pickAbsolver(absolverLink, screenshotsPick5); - } else { - await pickRemainingControl(controlLink, screenshotsPick5); - } + assertEquals(allPickedImagesNumber.length, 6); + assertEquals(allPickedImagesNumber.sort(), [1, 1, 1, 2, 4, 4]); + assertEquals(allPickedImagesIDs.length, 13); + assertEquals(allPickedPlatforms.length, 6); + assertEquals(allPickedPlatforms.sort(), [ + "Nintendo Switch", + "PC", + "PC", + "PC", + "PC", + "PC", + ]); + assertEquals(allPickedTitles.length, 6); + assertEquals(allPickedTitles.sort(), [ + "8-Bit Bayonetta", + "80's Overdrive", + "80's Overdrive", + "Absolver", + "Control", + "Control", + ]); - const screenshotsPick6: VideoGameScreeshotsToShare = - (await pickerService.pick()) as VideoGameScreeshotsToShare; - const pick6index: number = possibleTitles.indexOf(screenshotsPick6.title); - assert(pick6index >= 0); - assertNotEquals(pick6index, pick4index); - assertNotEquals(pick6index, pick5index); - - if (pick6index === 0) { - await pickOverdrivePC(overdriveLink, screenshotsPick6); - } else if (pick6index === 1) { - await pickAbsolver(absolverLink, screenshotsPick6); - } else { - await pickRemainingControl(controlLink, screenshotsPick6); + assertEquals(await pickerService.pick(), undefined); + } finally { + kvDriver.close(); } } -async function pickOverdrivePC( - possibleLink: VideoGameRelationImageRepositoryEntity, - pick: VideoGameScreeshotsToShare, -): Promise { - console.log("80s Overdrive PC picked"); - assertEquals(pick.screenshots.length, 1); - assertEquals(pick.screenshots[0].id, possibleLink.imageID); - assertEquals(pick.platform, "PC"); - assertEquals(pick.title, "80's Overdrive"); - await publishLink(possibleLink); -} - -async function pickAbsolver( - possibleLink: VideoGameRelationImageRepositoryEntity, - pick: VideoGameScreeshotsToShare, -): Promise { - console.log("Absolver picked"); - assertEquals(pick.screenshots.length, 1); - assertEquals(pick.screenshots[0].id, possibleLink.imageID); - assertEquals(pick.platform, "PC"); - assertEquals(pick.title, "Absolver"); - await publishLink(possibleLink); -} - -async function pickRemainingControl( - controlLink: VideoGameRelationImageRepositoryEntity, - pick: VideoGameScreeshotsToShare, -): Promise { - console.log("Control picked"); - assertEquals(pick.screenshots.length, 1); - assertEquals(pick.screenshots[0].id, controlLink.imageID); - assertEquals(pick.platform, "PC"); - assertEquals(pick.title, "Control"); - await publishLink(controlLink); -} - async function publishLinks( links: VideoGameRelationImageRepositoryEntity[], ): Promise { diff --git a/test/publish.test.ts b/test/publish.test.ts index d8dbc4e..874923f 100644 --- a/test/publish.test.ts +++ b/test/publish.test.ts @@ -1,4 +1,9 @@ -import { assertEquals, assertNotEquals } from "@std/assert"; +import { + assert, + assertEquals, + assertMatch, + assertNotEquals, +} from "@std/assert"; import { afterAll, beforeAll, @@ -70,14 +75,16 @@ describe("main publish", () => { await publish(action, driver, mockLogger()); assertNotEquals(mockedBlueskyServer.lastRecord, undefined); - assertEquals( - mockedBlueskyServer.lastRecord?.text, - 'Screenshots from video game "80\'s Overdrive" (2017) taken on Nintendo Switch', + assertMatch( + mockedBlueskyServer.lastRecord?.text ?? "", + /^Screenshots? from video game ".+" \(\d+\) taken on .+$/, ); - assertEquals(mockedBlueskyServer.lastRecord?.embed.images.length, 4); - assertEquals( - mockedBlueskyServer.lastRecord?.embed.images[0].alt, - "Screenshot from video game 80's Overdrive (no more details given by the bot)", + const publishedImages: number = + mockedBlueskyServer.lastRecord?.embed.images.length ?? 0; + assert(publishedImages > 0); + assertMatch( + mockedBlueskyServer.lastRecord?.embed.images[0].alt ?? "", + /^Screenshot from video game .+ \(no more details given by the bot\)$/, ); assertNotEquals( mockedBlueskyServer.lastRecord?.embed.images[0].image, @@ -88,7 +95,11 @@ describe("main publish", () => { await getAllRelationsFromRepository(tempDatabaseFilePath); assertEquals(allRelations.length, 8); - assertEquals(allRelations.filter((r) => r.published === true).length, 4); + assert(allRelations.filter((r) => r.published === true).length > 0); + assertEquals( + allRelations.filter((r) => r.published === true).length, + publishedImages, + ); } finally { driver.close(); }