From 77e48b8139778a6e930520108f7e06a6637d803e Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 19 Apr 2026 16:59:04 +0200 Subject: [PATCH 1/2] feat: Implement live environment loading and update race storage metadata handling --- faceai/playwright.live.config.js | 3 ++ faceai/probe.js | 47 ----------------- faceai/tests/live-site/live-race.spec.js | 30 ++++++----- .../tests/live-site/live-site-test-utils.js | 3 ++ faceai/tests/live-site/load-live-env.js | 52 +++++++++++++++++++ sync/www-deploy-manifest.md | 5 +- www/fotoCR-en.jsp | 18 ------- www/fotoCR.jsp | 18 ------- 8 files changed, 76 insertions(+), 100 deletions(-) delete mode 100644 faceai/probe.js create mode 100644 faceai/tests/live-site/load-live-env.js diff --git a/faceai/playwright.live.config.js b/faceai/playwright.live.config.js index 423f1795..687f7f86 100644 --- a/faceai/playwright.live.config.js +++ b/faceai/playwright.live.config.js @@ -1,5 +1,8 @@ const path = require('path'); const { defineConfig } = require('@playwright/test'); +const { loadLiveEnv } = require('./tests/live-site/load-live-env'); + +loadLiveEnv(); const authFile = path.join(__dirname, 'tests/live-site/.auth/user.json'); diff --git a/faceai/probe.js b/faceai/probe.js deleted file mode 100644 index e20ca7bb..00000000 --- a/faceai/probe.js +++ /dev/null @@ -1,47 +0,0 @@ -const { chromium } = require('playwright'); -const fs = require('fs'); - -async function run() { - const browser = await chromium.launch(); - const context = await browser.newContext(); - const page = await context.newPage(); - - try { - const loginUrl = process.env.LIVE_SITE_LOGIN_URL; - const raceUrl = process.env.LIVE_SITE_RACE_URL; - - console.log('--- Step 1: Navigating to Login ---'); - await page.goto(loginUrl, { waitUntil: 'load' }); - - console.log('--- Step 2: Filling credentials ---'); - await page.type('#login', process.env.LIVE_SITE_USERNAME); - await page.type('#pwd', process.env.LIVE_SITE_PASSWORD); - - console.log('--- Step 3: Clicking Accedi ---'); - await page.click('button:has-text("Accedi")'); - await page.waitForTimeout(5000); // Give it time to process and redirect - - console.log('--- Step 4: Navigating to Race Page ---'); - const response = await page.goto(raceUrl, { waitUntil: 'load' }); - - console.log('Race Page URL:', page.url()); - console.log('HTTP Status:', response.status()); - - const cookies = await context.cookies(); - const cookieNames = cookies.map(c => c.name); - console.log('Cookies:', cookieNames.join(', ')); - console.log('rus_faceai_identity:', cookieNames.includes('rus_faceai_identity')); - console.log('JSESSIONID:', cookieNames.includes('JSESSIONID')); - - const logoutCount = await page.locator('a[href*="logout"]').count(); - const loginCount = await page.locator('a[href*="login"]').count(); - console.log('Logout Link Count:', logoutCount); - console.log('Login Link Count:', loginCount); - - } catch (err) { - console.error('Error occurred:', err.message); - } finally { - await browser.close(); - } -} -run(); diff --git a/faceai/tests/live-site/live-race.spec.js b/faceai/tests/live-site/live-race.spec.js index 8806de5c..40b0a642 100644 --- a/faceai/tests/live-site/live-race.spec.js +++ b/faceai/tests/live-site/live-race.spec.js @@ -11,11 +11,16 @@ const { const LIVE_EXPECTED_RACE_STORAGE = { year: '2026', - monthFolder: '04.APRILE', + monthFolder: '03.MARZO', raceFolder: 'HMF_2026', - relativeDir: '2026/04.APRILE/HMF_2026' + relativeDir: '2026/03.MARZO/HMF_2026' }; +const LIVE_SAMPLE_PHOTO_IDS = [ + '21.ARRIVO_CON TEMPO\\DSC_8385.JPG', + '21.ARRIVO_CON TEMPO\\DSC_8295.JPG' +]; + function escapeRegExp(value) { return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } @@ -175,10 +180,7 @@ async function expectLegacyFaceAiGalleryToRemainStable(page, expectedPhotoIds, h } test('renders the exact live FaceAI filtered sample URL with visible thumbnails', async ({ page }) => { - const samplePhotoIds = [ - '00.PANORAMICA\\GIC_7918.JPG', - '02.PARTENZA\\GIC_7918.JPG' - ]; + const samplePhotoIds = LIVE_SAMPLE_PHOTO_IDS; const sampleUrl = `${LIVE_SITE_BASE_URL}/42%20HALF%20MARATHON%20FIRENZE_gara-1018545---48-1.html?faceaiMatchSource=faceai&faceaiMatchCount=2&faceaiPhotoIds=${encodeURIComponent(samplePhotoIds.join(','))}`; await ensureLiveAuthenticatedRacePage(page); @@ -197,7 +199,7 @@ test('renders the exact live FaceAI filtered sample URL with visible thumbnails' await expectLegacyFaceAiGalleryToRemainStable(page, samplePhotoIds); }); -test('keeps the live Firenze FaceAI race storage metadata pinned to April 2026', async ({ page }) => { +test('keeps the live Firenze FaceAI race storage metadata pinned to the stored server path', async ({ page }) => { await ensureLiveAuthenticatedRacePage(page); await expect(page.locator('#faceAiRaceYear')).toHaveValue(LIVE_EXPECTED_RACE_STORAGE.year); @@ -217,10 +219,7 @@ test('keeps the live Firenze FaceAI race storage metadata pinned to April 2026', }); test('resolves the live Firenze sample photo lookups inside the current race', async ({ page }) => { - const samplePhotoIds = [ - '00.PANORAMICA\\GIC_7918.JPG', - '02.PARTENZA\\GIC_7918.JPG' - ]; + const samplePhotoIds = LIVE_SAMPLE_PHOTO_IDS; await ensureLiveAuthenticatedRacePage(page); @@ -302,10 +301,9 @@ test('returns to the live race page from FaceAI without leaving the legacy spinn expect(bodyState.ariaBusy).not.toBe('true'); }); -test.skip(!LIVE_SITE_RUN_UPLOAD_FLOW, 'Set LIVE_SITE_RUN_UPLOAD_FLOW=1 to exercise the live upload flow.'); - test('accepts the supplied portrait image for the live upload flow', async ({ page }) => { test.slow(); + test.skip(!LIVE_SITE_RUN_UPLOAD_FLOW, 'Set LIVE_SITE_RUN_UPLOAD_FLOW=1 to exercise the live upload flow.'); requirePortraitFixture(); @@ -356,6 +354,12 @@ test('accepts the supplied portrait image for the live upload flow', async ({ pa const expectedPhotoIds = (finalUrl.searchParams.get('faceaiPhotoIds') || '').split(',').map((value) => value.trim()).filter(Boolean); expect(expectedPhotoIds.length, 'Expected the final race page URL to include at least one FaceAI photo identifier.').toBeGreaterThan(0); + for (const photoKey of expectedPhotoIds) { + const lookup = await lookupLivePhoto(page, photoKey); + expect(lookup.status, `Expected FaceAI to return a photo key that resolves on the current live race page: ${photoKey}`).toBe(200); + expect(lookup.payload && lookup.payload.found, `Expected FaceAI to return a photo key that exists in the current live race: ${photoKey}`).toBe(true); + } + const visiblePhotoIds = await waitForVisibleLegacyPhotoIds(page, expectedPhotoIds.length); expect(visiblePhotoIds.length, 'Expected at least one legacy race thumbnail to remain visible after FaceAI filtering.').toBeGreaterThan(0); expect(visiblePhotoIds.sort()).toEqual(expectedPhotoIds.slice().sort()); diff --git a/faceai/tests/live-site/live-site-test-utils.js b/faceai/tests/live-site/live-site-test-utils.js index 6f3992e7..6d646fb9 100644 --- a/faceai/tests/live-site/live-site-test-utils.js +++ b/faceai/tests/live-site/live-site-test-utils.js @@ -1,6 +1,9 @@ const fs = require('fs'); const path = require('path'); const { expect } = require('@playwright/test'); +const { loadLiveEnv } = require('./load-live-env'); + +loadLiveEnv(); const WORKSPACE_ROOT = path.resolve(__dirname, '..', '..', '..'); const LIVE_SITE_BASE_URL = process.env.LIVE_SITE_BASE_URL || 'https://www.regalamiunsorriso.it'; diff --git a/faceai/tests/live-site/load-live-env.js b/faceai/tests/live-site/load-live-env.js new file mode 100644 index 00000000..5327a20b --- /dev/null +++ b/faceai/tests/live-site/load-live-env.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const path = require('path'); + +let loaded = false; + +function parseEnvLine(line) { + const trimmed = String(line || '').trim(); + if (!trimmed || trimmed.startsWith('#')) { + return null; + } + + const separatorIndex = trimmed.indexOf('='); + if (separatorIndex <= 0) { + return null; + } + + const key = trimmed.slice(0, separatorIndex).trim(); + let value = trimmed.slice(separatorIndex + 1).trim(); + + if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { + value = value.slice(1, -1); + } + + return { key, value }; +} + +function loadLiveEnv() { + if (loaded) { + return; + } + + loaded = true; + + const envPath = path.resolve(__dirname, '..', '..', '.env'); + if (!fs.existsSync(envPath)) { + return; + } + + const envText = fs.readFileSync(envPath, 'utf8'); + for (const line of envText.split(/\r?\n/)) { + const entry = parseEnvLine(line); + if (!entry || !entry.key || Object.prototype.hasOwnProperty.call(process.env, entry.key)) { + continue; + } + + process.env[entry.key] = entry.value; + } +} + +module.exports = { + loadLiveEnv +}; \ No newline at end of file diff --git a/sync/www-deploy-manifest.md b/sync/www-deploy-manifest.md index aa23164b..5dc6cde7 100644 --- a/sync/www-deploy-manifest.md +++ b/sync/www-deploy-manifest.md @@ -14,9 +14,6 @@ All files in this rollout are deployed from the current working tree. ## Updated Files -- `www/_js/rus-ecom-240621.js` -- `www/faceai_return.php` -- `www/faceai_photo_lookup.jsp` - `www/fotoCR.jsp` - `www/fotoCR-en.jsp` @@ -30,7 +27,7 @@ All files in this rollout are deployed from the current working tree. - Remote host: `marco@83.149.164.4:410` - Remote staging path: `/home/marco/regalamiunsorriso/incoming/www` - Remote live path: `/home/sites/regalamiunsorriso/www` -- Total files in this manifest: `5` +- Total files in this manifest: `2` ## Transfer Method diff --git a/www/fotoCR-en.jsp b/www/fotoCR-en.jsp index a992adca..a999d2d0 100644 --- a/www/fotoCR-en.jsp +++ b/www/fotoCR-en.jsp @@ -60,23 +60,11 @@ boolean faceAiFeatureEnabled = !("0".equals(faceAiFeatureEnabledNormalized) || " <%@ include file="_inc_faceai_identity.jsp" %> <% -java.util.Date faceAiRaceDate = CR.getGara().getDataGaraInizio(); String faceAiRacePathBase = CR.getGara().getPathBase() != null ? CR.getGara().getPathBase().trim() : ""; String faceAiRaceYear = ""; String faceAiRaceMonthFolder = ""; String faceAiRaceFolder = ""; String faceAiRaceStorageRelativeDir = ""; -String faceAiExpectedYear = ""; -String faceAiExpectedMonthFolder = ""; -if (faceAiRaceDate != null) { - java.util.Calendar faceAiCalendar = java.util.Calendar.getInstance(); - String[] faceAiMonthNames = new String[] { "GENNAIO", "FEBBRAIO", "MARZO", "APRILE", "MAGGIO", "GIUGNO", "LUGLIO", "AGOSTO", "SETTEMBRE", "OTTOBRE", "NOVEMBRE", "DICEMBRE" }; - int faceAiMonthIndex; - faceAiCalendar.setTime(faceAiRaceDate); - faceAiExpectedYear = String.valueOf(faceAiCalendar.get(java.util.Calendar.YEAR)); - faceAiMonthIndex = faceAiCalendar.get(java.util.Calendar.MONTH); - faceAiExpectedMonthFolder = String.format("%02d.%s", new Object[] { Integer.valueOf(faceAiMonthIndex + 1), faceAiMonthNames[faceAiMonthIndex] }); -} if (!faceAiRacePathBase.isEmpty()) { String[] faceAiPathSegments = faceAiRacePathBase.replace('\\', '/').split("/"); java.util.ArrayList faceAiNormalizedSegments = new java.util.ArrayList(); @@ -114,12 +102,6 @@ if (!faceAiRacePathBase.isEmpty()) { } } } -if (!faceAiExpectedYear.isEmpty() && !faceAiExpectedYear.equals(faceAiRaceYear)) { - faceAiRaceYear = faceAiExpectedYear; -} -if (!faceAiExpectedMonthFolder.isEmpty() && !faceAiExpectedMonthFolder.equals(faceAiRaceMonthFolder)) { - faceAiRaceMonthFolder = faceAiExpectedMonthFolder; -} if (faceAiRaceFolder.isEmpty()) { faceAiRaceFolder = String.valueOf(CR.getGara().getId_gara()); } diff --git a/www/fotoCR.jsp b/www/fotoCR.jsp index 1a567482..2b9c6490 100644 --- a/www/fotoCR.jsp +++ b/www/fotoCR.jsp @@ -60,23 +60,11 @@ boolean faceAiFeatureEnabled = !("0".equals(faceAiFeatureEnabledNormalized) || " <%@ include file="_inc_faceai_identity.jsp" %> <% -java.util.Date faceAiRaceDate = CR.getGara().getDataGaraInizio(); String faceAiRacePathBase = CR.getGara().getPathBase() != null ? CR.getGara().getPathBase().trim() : ""; String faceAiRaceYear = ""; String faceAiRaceMonthFolder = ""; String faceAiRaceFolder = ""; String faceAiRaceStorageRelativeDir = ""; -String faceAiExpectedYear = ""; -String faceAiExpectedMonthFolder = ""; -if (faceAiRaceDate != null) { - java.util.Calendar faceAiCalendar = java.util.Calendar.getInstance(); - String[] faceAiMonthNames = new String[] { "GENNAIO", "FEBBRAIO", "MARZO", "APRILE", "MAGGIO", "GIUGNO", "LUGLIO", "AGOSTO", "SETTEMBRE", "OTTOBRE", "NOVEMBRE", "DICEMBRE" }; - int faceAiMonthIndex; - faceAiCalendar.setTime(faceAiRaceDate); - faceAiExpectedYear = String.valueOf(faceAiCalendar.get(java.util.Calendar.YEAR)); - faceAiMonthIndex = faceAiCalendar.get(java.util.Calendar.MONTH); - faceAiExpectedMonthFolder = String.format("%02d.%s", new Object[] { Integer.valueOf(faceAiMonthIndex + 1), faceAiMonthNames[faceAiMonthIndex] }); -} if (!faceAiRacePathBase.isEmpty()) { String[] faceAiPathSegments = faceAiRacePathBase.replace('\\', '/').split("/"); java.util.ArrayList faceAiNormalizedSegments = new java.util.ArrayList(); @@ -114,12 +102,6 @@ if (!faceAiRacePathBase.isEmpty()) { } } } -if (!faceAiExpectedYear.isEmpty() && !faceAiExpectedYear.equals(faceAiRaceYear)) { - faceAiRaceYear = faceAiExpectedYear; -} -if (!faceAiExpectedMonthFolder.isEmpty() && !faceAiExpectedMonthFolder.equals(faceAiRaceMonthFolder)) { - faceAiRaceMonthFolder = faceAiExpectedMonthFolder; -} if (faceAiRaceFolder.isEmpty()) { faceAiRaceFolder = String.valueOf(CR.getGara().getId_gara()); } From 0926c52a00db3ca88ac8f25546becedaabc5efed Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 19 Apr 2026 17:24:33 +0200 Subject: [PATCH 2/2] feat: Refactor multicore selection and enhance output handling in face encoder script --- .../run_face_encoder.ps1 | 45 ++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/bin/Face_Recognition_Windows/run_face_encoder.ps1 b/bin/Face_Recognition_Windows/run_face_encoder.ps1 index 3dab9662..9cd9417a 100644 --- a/bin/Face_Recognition_Windows/run_face_encoder.ps1 +++ b/bin/Face_Recognition_Windows/run_face_encoder.ps1 @@ -7,10 +7,10 @@ Write-Host " 3 = 1/2 dei core (predefinito)" Write-Host " 4 = 3/4 dei core" Write-Host " 5 = n-2 core" Write-Host "" -$input = Read-Host "Inserisci il livello (1-5) oppure premi Invio per usare il predefinito (3)" +$multicoreChoice = Read-Host "Inserisci il livello (1-5) oppure premi Invio per usare il predefinito (3)" -if ($input -match '^[1-5]$') { - $multicore = [int]$input +if ($multicoreChoice -match '^[1-5]$') { + $multicore = [int]$multicoreChoice } else { $multicore = -1 } @@ -94,13 +94,33 @@ if (-not $inputPath) { exit 0 } +$inputFolder = Get-Item -LiteralPath $inputPath -ErrorAction Stop +$raceName = $inputFolder.Name +$safeRaceName = ($raceName -replace '[<>:"/\\|?*]', ' ').Trim() +$safeRaceName = $safeRaceName -replace '\s+', '_' +if (-not $safeRaceName) { + $safeRaceName = 'race' +} + +$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss' +$encoderDir = Join-Path $PSScriptRoot "face_encoder_cpu" +$outputDir = Join-Path $encoderDir "output" +$outputFile = Join-Path $outputDir ("face_encodings_{0}_{1}.pkl" -f $timestamp, $safeRaceName) +$logFile = Join-Path $outputDir ("encoder_log_{0}_{1}.txt" -f $timestamp, $safeRaceName) + +New-Item -ItemType Directory -Path $outputDir -Force | Out-Null + # --- Build argument list --- -$encoderExe = Join-Path $PSScriptRoot "face_encoder_cpu\face_encoder_cpu.exe" +$encoderExe = Join-Path $encoderDir "face_encoder_cpu.exe" $encoderArgs = [System.Collections.Generic.List[string]]::new() $encoderArgs.Add("-i") -$encoderArgs.Add($inputPath) +$encoderArgs.Add($inputFolder.FullName) $encoderArgs.Add("-r") +$encoderArgs.Add("-o") +$encoderArgs.Add($outputFile) +$encoderArgs.Add("-l") +$encoderArgs.Add($logFile) if ($multicore -ge 0) { $encoderArgs.Add("-m") @@ -108,9 +128,22 @@ if ($multicore -ge 0) { } # --- Run encoder --- -Write-Host "Input folder : $inputPath" +Write-Host "Input folder : $($inputFolder.FullName)" +Write-Host "Race name : $raceName" Write-Host "Multicore : $(if ($multicore -ge 0) { $multicore } else { 'default (3)' })" +Write-Host "Output file : $outputFile" +Write-Host "Log file : $logFile" Write-Host "Command : $encoderExe $encoderArgs" Write-Host "" & $encoderExe @encoderArgs + +$encoderExitCode = $LASTEXITCODE + +if ($encoderExitCode -eq 0 -and (Test-Path -LiteralPath $outputFile)) { + Start-Process explorer.exe "/select,`"$outputFile`"" +} elseif ($encoderExitCode -eq 0) { + Write-Warning "Encoding completed, but the expected output file was not found: $outputFile" +} + +exit $encoderExitCode