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 Use •
Contributing •
Credits •
+ Authors •
License •
- 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();
}