using System.Collections.Generic; namespace LaDOSE.Entity { /// /// One spreadsheet write: the tables to put in it, and which spreadsheet. /// Not an entity — never mapped by EF. It arrives as SheetExportRequestDTO and is /// mapped by AutoMapper, same pattern as , so property names /// must stay identical to the DTO's. /// /// The tables are built client-side by $lib/tournaments/cumulative.ts, which reuses the /// very same buildRanking() that produces the CSV export. That is deliberate: the sheet /// and the CSV cannot drift because one function produces both. /// public class SheetExportRequest { /// /// Resolved by SheetsExportService from configuration — never supplied by the caller, /// so a client cannot aim the export at someone else's spreadsheet. /// public string SpreadsheetId { get; set; } /// /// One tab per selected event, oldest first. Tab N holds events 1..N merged, so the /// last tab is the full cumulative ranking for the scope. /// public List Tabs { get; set; } = new List(); } /// One tab: a players x games grid with a Total column. public class SheetTable { /// Desired tab title, e.g. "Ranking #1301". Sanitised before use. public string Name { get; set; } /// /// Provenance and logging only. Tabs are addressed by title, never by this — see the /// note on tab identity in SheetsExportService. /// public int EventId { get; set; } /// ["Players", <game names...>, "Total"]. public List Header { get; set; } = new List(); public List Rows { get; set; } = new List(); /// /// Written below the grid, one line per entry, blank row in between. Carries which /// events went into this tab so a stale or incomplete tab identifies itself. /// public List Footer { get; set; } = new List(); } public class SheetRow { public string Player { get; set; } /// Index-aligned with Header[1..^1] — one entry per game column. public List Points { get; set; } = new List(); public int Total { get; set; } } public class SheetExportResult { public string SpreadsheetId { get; set; } public string SpreadsheetUrl { get; set; } /// Which ISheetsWriter did the work — "ServiceAccount", "Logging", ... public string Writer { get; set; } public List Tabs { get; set; } = new List(); /// Anything the user should know but that did not stop the write, e.g. renames. public List Warnings { get; set; } = new List(); } public class SheetTabResult { /// The title as asked for, before sanitisation. public string RequestedName { get; set; } /// The title actually written to. public string Name { get; set; } public int Rows { get; set; } public int Columns { get; set; } /// False when an existing tab of that name was rewritten in place. public bool Created { get; set; } } /// What the UI needs to render the export panel. Never carries a secret. public class SheetsConfig { public string Writer { get; set; } /// The writer has its credentials and a target spreadsheet is configured. public bool Configured { get; set; } public string SpreadsheetId { get; set; } public int MaxTabs { get; set; } public int MaxRowsPerTab { get; set; } } /// /// Server-side limits and the target spreadsheet, read from the GoogleSheets configuration /// section. Constructor-injected rather than IOptions, matching how the Challonge and Smash /// providers take their keys. /// public class SheetsSettings { /// /// The spreadsheet everything is written to. Reset each year — see .env.example. /// public string SpreadsheetId { get; set; } public int MaxTabs { get; set; } = 60; public int MaxRowsPerTab { get; set; } = 5000; /// Google caps a tab at 100 chars; this caps the grid width. public int MaxColumns { get; set; } = 200; } }