diff --git a/ems-api/src/controllers/Ranking.ts b/ems-api/src/controllers/Ranking.ts index a766fe4..acc49b7 100644 --- a/ems-api/src/controllers/Ranking.ts +++ b/ems-api/src/controllers/Ranking.ts @@ -33,9 +33,10 @@ router.get("/calculate/:tournament_level", (req: Request, res: Response, next: N logger.info(`Re-calculating rankings for ${req.query.type}.`); const ranker: IMatchRanker = getRankerByType(req.query.type); const rankJSON: any = ranker.execute(rows).map((rank: IPostableObject) => rank.toJSON()); - if (rankJSON.length > 0){ + if (rankJSON.length > 0) { const promises: Array> = []; for (const ranking of rankJSON) { + if (typeof ranking.team !== "undefined") delete ranking.team; promises.push(DatabaseManager.updateWhere("ranking", ranking, "rank_key=\"" + ranking.rank_key + "\"")); } Promise.all(promises).then((values: any[]) => { diff --git a/ems-core/package.json b/ems-core/package.json index abb59de..d020abc 100644 --- a/ems-core/package.json +++ b/ems-core/package.json @@ -4,7 +4,7 @@ "private": true, "main": "build/electron.js", "dependencies": { - "@the-orange-alliance/lib-ems": "^0.5.7", + "@the-orange-alliance/lib-ems": "^0.5.12", "axios": "^0.19.0", "dotenv": "^8.0.0", "local-ipv4-address": "0.0.2", diff --git a/ems-core/src/App.tsx b/ems-core/src/App.tsx index a8c9292..4c9c963 100644 --- a/ems-core/src/App.tsx +++ b/ems-core/src/App.tsx @@ -9,8 +9,9 @@ import { incrementCompletedStep, setAllianceMembers, setSocketConnected, } from "./stores/internal/actions"; -import {EMSProvider, FGCProvider, TOAProvider, SocketProvider, WebProvider, TOAConfig, MatchConfiguration, +import {EMSProvider, SocketProvider, WebProvider, TOAConfig, MatchConfiguration, AllianceMember} from "@the-orange-alliance/lib-ems"; +import UploadManager from "./managers/UploadManager"; interface IProps { slaveModeEnabled: boolean, @@ -28,12 +29,9 @@ class App extends React.Component { public componentDidMount() { if (this.props.toaConfig.enabled) { - TOAProvider.initialize(this.props.toaConfig); + UploadManager.initialize(1, this.props.toaConfig); } - // Debug - FGCProvider.initialize("127.0.0.1", 8088); - this.initializeSocket(this.props.networkHost); WebProvider.initialize(this.props.networkHost); if (this.props.slaveModeEnabled) { diff --git a/ems-core/src/components/SetupMatchScheduleOverview.tsx b/ems-core/src/components/SetupMatchScheduleOverview.tsx index 930ac6d..4194a28 100644 --- a/ems-core/src/components/SetupMatchScheduleOverview.tsx +++ b/ems-core/src/components/SetupMatchScheduleOverview.tsx @@ -146,7 +146,6 @@ class SetupMatchScheduleOverview extends React.Component { private publish() { this.closeConfirmModal(); this.props.onComplete(this.state.postOnline); - console.log(this.state.postOnline); } } diff --git a/ems-core/src/managers/FGCUploadedManager.ts b/ems-core/src/managers/FGCUploadManager.ts similarity index 74% rename from ems-core/src/managers/FGCUploadedManager.ts rename to ems-core/src/managers/FGCUploadManager.ts index 0a0306c..b699a7c 100644 --- a/ems-core/src/managers/FGCUploadedManager.ts +++ b/ems-core/src/managers/FGCUploadManager.ts @@ -1,4 +1,7 @@ -import {EMSProvider, FGCProvider, HttpError, Match, MatchDetails, MatchParticipant, Ranking, Team} from "@the-orange-alliance/lib-ems"; +import { + EMSProvider, Event, FGCProvider, HttpError, Match, MatchDetails, MatchParticipant, Ranking, Team +} from "@the-orange-alliance/lib-ems"; +import TeamValidator from "../validators/TeamValidator"; class FGCUploadedManager { private static _instance: FGCUploadedManager; @@ -12,6 +15,39 @@ class FGCUploadedManager { private constructor() {} + public getEvent(eventKey: string): Promise { + return new Promise((resolve, reject) => { + FGCProvider.getEvent(eventKey).then((event: Event) => { + if (event && event.eventKey && event.eventKey.length > 0) { + resolve(event); + } else { + reject(); + } + }).catch((error: HttpError) => { + reject(error); + }); + + }); + } + + public getTeams(eventKey: string): Promise { + return new Promise((resolve, reject) => { + FGCProvider.getTeams(eventKey).then((participants: Team[]) => { + const teams: Team[] = []; + for (const participant of participants) { + const validator: TeamValidator = new TeamValidator(participant); + validator.update(participant); + if (validator.isValid) { + teams.push(participant); + } + } + resolve(teams); + }).catch((error: HttpError) => { + reject(error); + }); + }); + } + public postEventParticipants(eventKey: string, teams: Team[]): Promise { return new Promise((resolve, reject) => { FGCProvider.deleteTeams(eventKey).then(() => { @@ -33,7 +69,7 @@ class FGCUploadedManager { FGCProvider.deleteMatchData(eventKey, matches[0].tournamentLevel).then(() => { setTimeout(() => { const fgcMatches: Match[] = matches.map((m: Match) => m); - const fgcDetails: MatchDetails[] = matches.map((m: Match) => m.matchDetails); + const fgcDetails: MatchDetails[] = matches.map((m: Match) => new MatchDetails().fromJSON({match_key: m.matchKey, match_detail_key: m.matchDetailKey})); const fgcParticipants: MatchParticipant[] = []; for (const match of matches) { for (const participant of match.participants) { diff --git a/ems-core/src/managers/TOAUploadManager.ts b/ems-core/src/managers/TOAUploadManager.ts index 4411a8f..4e4d670 100644 --- a/ems-core/src/managers/TOAUploadManager.ts +++ b/ems-core/src/managers/TOAUploadManager.ts @@ -1,7 +1,10 @@ -import {EMSProvider, HttpError, Match, MatchDetails, MatchParticipant, Ranking, Team, +import { + EMSProvider, Event, HttpError, Match, MatchDetails, MatchParticipant, Ranking, Team, TOAEventParticipant, TOAEventParticipantAdapter, TOAMatch, TOAMatchAdapter, TOAMatchDetails, TOAMatchDetailsAdapter, - TOAMatchParticipant, TOAMatchParticipantAdapter, TOAProvider, TOARanking, TOARankingAdapter + TOAMatchParticipant, TOAMatchParticipantAdapter, TOAProvider, TOARanking, TOARankingAdapter, EMSEventAdapter, + TOAEvent, EMSTeamAdapter } from "@the-orange-alliance/lib-ems"; +import TeamValidator from "../validators/TeamValidator"; class TOAUploadManager { private static _instance: TOAUploadManager; @@ -15,6 +18,43 @@ class TOAUploadManager { private constructor() {} + public getEvent(eventKey: string): Promise { + return new Promise((resolve, reject) => { + TOAProvider.getEvent(eventKey).then((event: TOAEvent) => { + if (event && event.eventKey && event.eventKey.length > 0) { + resolve(new EMSEventAdapter(event).get()); + } else { + reject(); + } + }).catch((error: HttpError) => { + reject(error); + }); + + }); + } + + public getTeams(eventKey: string): Promise { + return new Promise((resolve, reject) => { + TOAProvider.getTeams(eventKey).then((toaParticipants: TOAEventParticipant[]) => { + const teams: Team[] = []; + for (const toaParticipant of toaParticipants) { + if (typeof toaParticipant.team !== "undefined") { + const team: Team = new EMSTeamAdapter(toaParticipant.team).get(); + team.participantKey = toaParticipant.eventParticipantKey; + const validator: TeamValidator = new TeamValidator(team); + validator.update(team); + if (validator.isValid) { + teams.push(team); + } + } + } + resolve(teams); + }).catch((error: HttpError) => { + reject(error); + }); + }); + } + public postEventParticipants(eventKey: string, teams: Team[]): Promise { return new Promise((resolve, reject) => { TOAProvider.deleteTeams(eventKey).then(() => { diff --git a/ems-core/src/managers/UploadManager.ts b/ems-core/src/managers/UploadManager.ts new file mode 100644 index 0000000..ed8781d --- /dev/null +++ b/ems-core/src/managers/UploadManager.ts @@ -0,0 +1,87 @@ +import {Event, FGCProvider, Match, Team, TOAConfig, TOAProvider} from "@the-orange-alliance/lib-ems"; +import TOAUploadManager from "./TOAUploadManager"; +import FGCUploadManager from "./FGCUploadManager"; + +class UploadManager { + public static TOA: number = 0; + public static FGC: number = 1; + + private static _instance: UploadManager; + + private _type: number; + + public static getInstance(): UploadManager { + if (typeof UploadManager._instance === "undefined") { + UploadManager._instance = new UploadManager(); + } + return UploadManager._instance; + } + + private constructor() {} + + public initialize(type: number, toaConfig: TOAConfig): void { + this._type = type; + if (this._type === UploadManager.TOA) { + TOAProvider.initialize(toaConfig); + } + if (this._type === UploadManager.FGC) { + FGCProvider.initialize("127.0.0.1", 8088); // DEBUG + } + } + + public getEvent(eventKey: string): Promise { + if (this._type === UploadManager.TOA) { + return TOAUploadManager.getEvent(eventKey); + } else if (this._type === UploadManager.FGC) { + return FGCUploadManager.getEvent(eventKey); + } else { + return new Promise((resolve, reject) => reject()); + } + } + + public getTeams(eventKey: string): Promise { + if (this._type === UploadManager.TOA) { + return TOAUploadManager.getTeams(eventKey); + } else if (this._type === UploadManager.FGC) { + return FGCUploadManager.getTeams(eventKey); + } else { + return new Promise((resolve, reject) => reject()); + } + } + + public postEventParticipants(eventKey: string, teams: Team[]): Promise { + if (this._type === UploadManager.TOA) { + return TOAUploadManager.postEventParticipants(eventKey, teams); + } else if (this._type === UploadManager.FGC) { + return FGCUploadManager.postEventParticipants(eventKey, teams); + } else { + return new Promise((resolve, reject) => reject()); + } + } + + public postMatchSchedule(eventKey: string, matches: Match[]): Promise { + if (this._type === UploadManager.TOA) { + return TOAUploadManager.postMatchSchedule(eventKey, matches); + } else if (this._type === UploadManager.FGC) { + return FGCUploadManager.postMatchSchedule(eventKey, matches); + } else { + return new Promise((resolve, reject) => reject()); + } + } + + public postMatchResults(eventKey: string, match: Match): Promise { + if (this._type === UploadManager.TOA) { + return TOAUploadManager.postMatchResults(eventKey, match); + } else if (this._type === UploadManager.FGC) { + return FGCUploadManager.postMatchResults(eventKey, match); + } else { + return new Promise((resolve, reject) => reject()); + } + } + +} + +export const TOA = UploadManager.TOA; +export const FGC = UploadManager.FGC; + +export default UploadManager.getInstance(); \ No newline at end of file diff --git a/ems-core/src/views/event-manager/views/EventParticipantSelection.tsx b/ems-core/src/views/event-manager/views/EventParticipantSelection.tsx index 1ae54eb..1bb5ab6 100644 --- a/ems-core/src/views/event-manager/views/EventParticipantSelection.tsx +++ b/ems-core/src/views/event-manager/views/EventParticipantSelection.tsx @@ -13,10 +13,10 @@ import TeamValidator from "../../../validators/TeamValidator"; import EventCreationManager from "../../../managers/EventCreationManager"; // import TOAUploadManager from "../../../managers/TOAUploadManager"; import { - EMSTeamAdapter, Event, EventConfiguration, HttpError, Team, TOAEventParticipant, TOAConfig, TOAProvider, + Event, EventConfiguration, HttpError, Team, TOAConfig, EliminationMatchesFormat } from "@the-orange-alliance/lib-ems"; -import FGCUploadedManager from "../../../managers/FGCUploadedManager"; +import UploadManager from "../../../managers/UploadManager"; interface IProps { onComplete: () => void, @@ -61,7 +61,7 @@ class EventParticipantSelection extends React.Component { this.createTestTeam = this.createTestTeam.bind(this); this.removeTeam = this.removeTeam.bind(this); this.importTeamsByCSV = this.importTeamsByCSV.bind(this); - this.importByTOA = this.importByTOA.bind(this); + this.importOnline = this.importOnline.bind(this); this.createTeamList = this.createTeamList.bind(this); } @@ -109,7 +109,7 @@ class EventParticipantSelection extends React.Component { { toaConfig.enabled && - + }
@@ -130,13 +130,8 @@ class EventParticipantSelection extends React.Component { updatedTeams[i].participantKey = this.props.event.eventKey + "-T" + this.props.teams[i].teamKey; } if (this.props.toaConfig.enabled) { - // TOAUploadManager.postEventParticipants(this.props.event.eventKey, updatedTeams).then(() => { - // console.log(`${updatedTeams.length} teams have been posted to TOA`); - // }).catch((error: HttpError) => { - // DialogManager.showErrorBox(error); - // }); - FGCUploadedManager.postEventParticipants(this.props.event.eventKey, updatedTeams).then(() => { - console.log(`${updatedTeams.length} teams have been posted to TOA`); + UploadManager.postEventParticipants(this.props.event.eventKey, updatedTeams).then(() => { + console.log(`${updatedTeams.length} teams have been posted online.`); }).catch((error: HttpError) => { DialogManager.showErrorBox(error); }); @@ -198,33 +193,14 @@ class EventParticipantSelection extends React.Component { }); } - private importByTOA() { + private importOnline() { this.setState({loadingTeams: true}); this.props.setNavigationDisabled(true); - TOAProvider.getTeams(this.props.event.eventKey).then((toaParticipants: TOAEventParticipant[]) => { - const teams: Team[] = []; - const failedImports: number[] = []; - for (const toaParticipant of toaParticipants) { - if (typeof toaParticipant.team !== "undefined") { - const team: Team = new EMSTeamAdapter(toaParticipant.team).get(); - team.participantKey = toaParticipant.eventParticipantKey; - const validator: TeamValidator = new TeamValidator(team); - validator.update(team); - if (validator.isValid) { - teams.push(team); - } else { - failedImports.push(team.teamKey); - } - } else { - failedImports.push(toaParticipant.teamKey); - } - } + UploadManager.getTeams(this.props.event.eventKey).then((teams: Team[]) => { this.setState({loadingTeams: false}); this.props.setNavigationDisabled(false); this.props.setTeamList(teams); - setTimeout(() => { - DialogManager.showInfoBox("Team Import Result", "Imported " + teams.length + " of original " + toaParticipants.length + ". The following teams were not imported due to parsing errors: " + failedImports.toString()); - }, 250); + DialogManager.showInfoBox("Team Import Result", "Imported " + teams.length + " teams from online."); }).catch((error: HttpError) => { this.setState({loadingTeams: false}); this.props.setNavigationDisabled(false); diff --git a/ems-core/src/views/event-manager/views/EventPracticeSetup.tsx b/ems-core/src/views/event-manager/views/EventPracticeSetup.tsx index d3af018..d07b7ee 100644 --- a/ems-core/src/views/event-manager/views/EventPracticeSetup.tsx +++ b/ems-core/src/views/event-manager/views/EventPracticeSetup.tsx @@ -12,9 +12,9 @@ import {Dispatch} from "redux"; import {disableNavigation, setPracticeMatches} from "../../../stores/internal/actions"; import EventCreationManager from "../../../managers/EventCreationManager"; import DialogManager from "../../../managers/DialogManager"; -import TOAUploadManager from "../../../managers/TOAUploadManager"; import {Event, EventConfiguration, HttpError, Match, Schedule, ScheduleItem, Team, TOAConfig} from "@the-orange-alliance/lib-ems"; import SetupScheduleParticipants from "../../../components/SetupScheduleParticipants"; +import UploadManager from "../../../managers/UploadManager"; interface IProps { onComplete: () => void, @@ -95,8 +95,8 @@ class EventPracticeSetup extends React.Component { private onPublishSchedule(postOnline: boolean) { this.props.setNavigationDisabled(true); if (postOnline && this.props.toaConfig.enabled) { - TOAUploadManager.postMatchSchedule(this.props.event.eventKey, this.props.practiceMatches).then(() => { - console.log(`${this.props.practiceMatches.length} matches have been posted to TOA.`); + UploadManager.postMatchSchedule(this.props.event.eventKey, this.props.practiceMatches).then(() => { + console.log(`${this.props.practiceMatches.length} matches have been posted online.`); }).catch((error: HttpError) => { DialogManager.showErrorBox(error); }); diff --git a/ems-core/src/views/event-manager/views/EventQualificationSetup.tsx b/ems-core/src/views/event-manager/views/EventQualificationSetup.tsx index 8bb7185..f59ed68 100644 --- a/ems-core/src/views/event-manager/views/EventQualificationSetup.tsx +++ b/ems-core/src/views/event-manager/views/EventQualificationSetup.tsx @@ -12,9 +12,9 @@ import {Dispatch} from "redux"; import {disableNavigation, setQualificationMatches} from "../../../stores/internal/actions"; import EventCreationManager from "../../../managers/EventCreationManager"; import DialogManager from "../../../managers/DialogManager"; -import TOAUploadManager from "../../../managers/TOAUploadManager"; import {Event, EventConfiguration, HttpError, Match, Schedule, ScheduleItem, Team, TOAConfig} from "@the-orange-alliance/lib-ems"; import SetupScheduleParticipants from "../../../components/SetupScheduleParticipants"; +import UploadManager from "../../../managers/UploadManager"; interface IProps { onComplete: () => void, @@ -95,7 +95,7 @@ class EventQualificationSetup extends React.Component { private onPublishSchedule() { this.props.setNavigationDisabled(true); if (this.props.toaConfig.enabled) { - TOAUploadManager.postMatchSchedule(this.props.event.eventKey, this.props.qualificationMatches).then(() => { + UploadManager.postMatchSchedule(this.props.event.eventKey, this.props.qualificationMatches).then(() => { console.log(`${this.props.qualificationMatches.length} matches have been posted to TOA.`); }).catch((error: HttpError) => { DialogManager.showErrorBox(error); diff --git a/ems-core/src/views/event-manager/views/EventSelection.tsx b/ems-core/src/views/event-manager/views/EventSelection.tsx index f085ada..1a95cca 100644 --- a/ems-core/src/views/event-manager/views/EventSelection.tsx +++ b/ems-core/src/views/event-manager/views/EventSelection.tsx @@ -23,13 +23,14 @@ import EventCreationManager from "../../../managers/EventCreationManager"; import { DropdownData, Event, EventConfiguration, HttpError, Match, PlayoffsType, Region, RegionData, SeasonData, - TOAConfig, TOAProvider, FGCProvider, DEFAULT_RESET, FTC_RELIC_PRESET, FGC_PRESET, FTC_ROVER_PRESET, + TOAConfig, DEFAULT_RESET, FTC_RELIC_PRESET, FGC_PRESET, FTC_ROVER_PRESET, EliminationMatchesFormat, RankingMatchesFormat, RoundRobinFormat, SeriesType, ROUND_ROBIN_PRESET, RANKING_PRESET, ELIMINATIONS_PRESET } from "@the-orange-alliance/lib-ems"; import NumericInput from "../../../components/NumericInput"; import MatchManager from "../../../managers/MatchManager"; import TournamentValidator from "../../../validators/TournamentValidator"; +import UploadManager, {FGC} from "../../../managers/UploadManager"; interface IProps { onComplete: () => void, @@ -289,27 +290,11 @@ class EventSelection extends React.Component { ); } - /* TOA Download Methods */ + /* Online Download Methods */ private downloadTOAData() { this.setState({downloadingData: true}); - TOAProvider.initialize(this.props.toaConfig); - // TOAProvider.getEvent(this.props.toaConfig.eventKey).then((toaEvent: TOAEvent) => { - // if (toaEvent && toaEvent.eventKey && toaEvent.eventKey.length > 0) { - // this.props.setEvent(new EMSEventAdapter(toaEvent).get()); - // this.props.toaConfig.enabled = true; - // this._validator.update(this.props.eventConfig, this.props.event); - // this.forceUpdate(); - // } else { - // DialogManager.showInfoBox("TheOrangeAlliance", `The Orange Alliance does not contain any event info for "${this.props.toaConfig.eventKey}". Are you sure your event information is posted online?`); - // } - // this.setState({downloadingData: false}); - // }).catch((error: HttpError) => { - // this.props.toaConfig.enabled = false; - // console.log(error); - // this.setState({downloadingData: false}); - // DialogManager.showErrorBox(error); - // }); - FGCProvider.getEvent(this.props.toaConfig.eventKey).then((event: Event) => { + UploadManager.initialize(FGC, this.props.toaConfig); + UploadManager.getEvent(this.props.toaConfig.eventKey).then((event: Event) => { if (event && event.eventKey && event.eventKey.length > 0) { this.props.setEvent(event); this.props.toaConfig.enabled = true; diff --git a/ems-core/src/views/match-play/containers/MatchPlay.tsx b/ems-core/src/views/match-play/containers/MatchPlay.tsx index cbfac42..2cf0b97 100644 --- a/ems-core/src/views/match-play/containers/MatchPlay.tsx +++ b/ems-core/src/views/match-play/containers/MatchPlay.tsx @@ -18,13 +18,13 @@ import DialogManager from "../../../managers/DialogManager"; import {IDisableNavigation} from "../../../stores/internal/types"; import {disableNavigation} from "../../../stores/internal/actions"; import GameSpecificScorecard from "../../../components/GameSpecificScorecard"; -import TOAUploadManager from "../../../managers/TOAUploadManager"; import { Event, EventConfiguration, HttpError, Match, MatchDetails, MatchConfiguration, MatchParticipant, MatchState, MatchTimer, SocketProvider, TOAConfig, TournamentType, EliminationMatchesFormat } from "@the-orange-alliance/lib-ems"; import InternalStateManager from "../../../managers/InternalStateManager"; import ConfirmActionModal from "../../../components/ConfirmActionModal"; +import UploadManager from "../../../managers/UploadManager"; interface IProps { mode: string, @@ -316,14 +316,15 @@ class MatchPlay extends React.Component { this.setState({committingScores: true}); this.props.activeMatch.matchDetails = this.props.activeDetails; this.props.activeMatch.participants = this.props.activeParticipants; - if (this.props.toaConfig.enabled) { - TOAUploadManager.postMatchResults(this.props.event.eventKey, this.props.activeMatch).then(() => { - console.log(`Uploaded match results for ${this.props.activeMatch.matchKey}`); - }).catch((error: HttpError) => { - DialogManager.showErrorBox(error); - }); - } MatchManager.commitScores(this.props.activeMatch, this.props.eventConfig).then(() => { + if (this.props.toaConfig.enabled) { + UploadManager.postMatchResults(this.props.event.eventKey, this.props.activeMatch).then(() => { + console.log(`Uploaded match results for ${this.props.activeMatch.matchKey}`); + }).catch((error: HttpError) => { + DialogManager.showErrorBox(error); + }); + } + this.props.setNavigationDisabled(false); this.props.setMatchState(MatchState.PRESTART_READY); this.setState({committingScores: false});