Aoe-Elo Logo

AoE Tournament Elo (Documentation)

🌐 Hosted here: https://aoe-elo.com (still the old backend)
🗨 Discord: https://discord.gg/hZzheB2kVE

License

The aoe-elo design documentation is open-source and licensed under the GNU Free Documentation License v1.3 or later.

Contributing

Protocols

2023-08-07 - Voice talk with @ghostmonkey

  • simonsan explained a few things regarding the backend, so it’s easier to determine how the Request-Business Logic-Response cycle works in it
    • basically web requests land in Routes/web.php, API requests land in Routes/api.php then you either use a Controller in app/http/Controllers/web/{e.g. PageController} to create a response in a method of that class or directly form a response in the corresponding function in {web,api}.php
  • simonsan talked about how data can be transferred to a svelte file (from my current knowledge, that might change as I’m diving deeper into laravel and inertia)
  • we talked about possible current and future use cases
  • simonsan sent players.json, teams.json, and tournaments.json response to work with for drafting on the frontend side
  • agreed on work split, so simonsan will work on the backend for now implementing/refactoring/migrating all the current existing business logic and ghostmonkey will continue to design the frontend
    • we talked about who has the final say on what is being done, and we assumed that we will all work together, waiting for feedback of participants in @here and go forward from there. in the end new things need to get used to, it’s normal.

Design

Personas

  1. Victor “Veteran” Sanchez

    • Age: 30
    • Background: A long-time fan of AoE II since its early days. Victor has been attending and watching tournaments for over a decade.
    • Goal: Wants to track how his favorite old-time players have evolved in rating over the years and reminisce about historical matches.
    • Behavior: Often discusses past matches and players in online forums.
  2. Lila “Newbie” Foster

    • Age: 19
    • Background: Recently introduced to the competitive scene of AoE II and is eager to learn about the top players and teams.
    • Goal: Wants an easy-to-understand overview of player ratings and their significance.
    • Behavior: Frequently searches for recent tournament results and player highlights.
  3. Raj “Analyst” Mehta

    • Age: 28
    • Background: A professional esports analyst who dives deep into match statistics to provide commentary and insights.
    • Goal: Needs detailed player performance metrics and rating histories for his analysis.
    • Behavior: Uses multiple platforms to gather game data and statistics.
  4. Elena “Team Manager” Vasquez

    • Age: 34
    • Background: Manages a competitive AoE II team.
    • Goal: Wants to scout potential talents and keep an eye on the competition.
    • Behavior: Regularly checks player profiles, especially rising stars.
  5. Mike “Casual Gamer” O’Donnell

    • Age: 24
    • Background: Enjoys playing AoE II casually and occasionally watches tournaments.
    • Goal: Curious about the best players and their strategies.
    • Behavior: Sporadically visits the webapp after major tournaments.
  6. Sophia “Journalist” Lee

    • Age: 27
    • Background: An esports journalist covering major tournaments and player stories.
    • Goal: Needs up-to-date player ratings and profiles for her articles.
    • Behavior: Frequently uses the webapp for references when writing or reporting.
  7. Hassan “Streamer” Farid

    • Age: 22
    • Background: Popular AoE II streamer who interacts with his fans about the competitive scene.
    • Goal: To stay informed about the competitive landscape and engage his viewers with relevant discussions.
    • Behavior: References the webapp during his live streams.
  8. Lucia “History Buff” Martinez

    • Age: 40
    • Background: Enthusiastic about the history of games and esports.
    • Goal: Enjoys diving deep into the historical aspect of the competitive AoE II scene.
    • Behavior: Spends time exploring past tournaments and player careers.
  9. Danielle “Organizer” Thompson

    • Age: 32
    • Background: A dedicated organizer of local and international AoE II tournaments. Danielle has been orchestrating gaming events for the past 7 years and has a great network within the AoE II community.
    • Goal: Wants to keep track of top players to invite for exhibition matches and to ensure fair seeding in her tournaments. Also wishes to monitor emerging talents to offer opportunities in her next events.
    • Behavior: Frequently checks the webapp for the latest player ratings, particularly after major tournaments, to make informed decisions about invitations and seeding. Additionally, she cross-references player performance metrics with their historical game records to anticipate potential fan-favorite matchups.
    • Additional Needs: A tool within the webapp that allows her to simulate tournament brackets based on current ratings, or an API she can connect with her own tournament management system.
  10. Jin “BladeMaster” Kim

    • Age: 26
    • Background: A professional AoE II player from South Korea, Jin has been playing since he was a teenager. He has won multiple regional tournaments and has recently made a significant impact on the international scene. He practices for hours daily and is a key player in his team.
    • Goal: Wants to monitor his own ratings and compare with other top players. Also interested in revisiting his past matches to learn from them and scout his potential competitors in upcoming tournaments.
    • Behavior: Checks the webapp frequently, especially after a tournament he participated in, to see how his performance affected his rating. He also watches replays of his own games and those of top competitors to analyze strategies.
    • Additional Needs: A detailed breakdown of his performance metrics over time. Access to match replays linked directly from the webapp. Notifications or alerts when significant rating changes occur or when new tournaments are added.

Use cases

  1. Victor “Veteran” Sanchez

    • View historical matches and player profiles.
    • Search for old-time players and their ratings.
  2. Lila “Newbie” Foster

    • View the current top players and their ratings.
    • Access a beginner’s guide or glossary on rating systems.
  3. Raj “Analyst” Mehta

    • Dive deep into player performance metrics.
    • Access detailed match statistics.
  4. Elena “Team Manager” Vasquez

    • View player profiles with an emphasis on recent performance.
    • Scout new talent based on performance trends.
  5. Mike “Casual Gamer” O’Donnell

    • Check summaries of recent major tournaments.
    • Browse player highlights and strategies.
  6. Sophia “Journalist” Lee

    • Access up-to-date player ratings.
    • Extract quotes or notable achievements for articles.
  7. Hassan “Streamer” Farid

    • Check real-time competitive landscape updates.
    • Engage viewers with player rating discussions.
  8. Lucia “History Buff” Martinez

    • Explore archived tournaments.
    • Track long-term player career arcs.
    • Annual breakdown, letting me see how active and competitive a player was in any given year
    • I want a user-friendly search function so I can quickly find tournaments from the past.
    • I’d like to pick two or more players and juxtapose their stats side by side
    • Being able to track and compare the ELO progression of players will let me analyze patterns and significant moments in their careers.
    • I want to be able to search and study retired players too.
    • When viewing a player’s profile, seeing a neat and organized display of their victories and milestones will help me appreciate their journey.
    • It’s not always about the money, but it’s interesting to see the financial rewards players have garnered over the years.
    • Knowing who a player’s main rivals were and who they consistently struggled against or triumphed over tells a more vivid story.
    • I want to understand a player’s affiliations and the teams they’ve played with, offering another dimension to their competitive journey.
    • Having direct links to game footage lets me study and appreciate gameplay, especially from significant or iconic matches.
  9. Danielle “Organizer” Thompson

    • Access up-to-date player ratings for seeding.
    • Simulate tournament brackets.
    • Monitor emerging talents for invitations.
  10. Jin “BladeMaster” Kim

    • Jin wants to check his current rating and see how it has changed after a recent tournament.
    • Jin is interested in comparing his rating with other top players to gauge his position in the competitive scene.
    • Jin wants to receive alerts or notifications when his rating changes or when there’s an update about a new tournament.

User stories

These are written from the perspective of the user, detailing what they want to achieve.

  1. Victor “Veteran” Sanchez

    • As a long-time fan, I want to view historical matches so that I can reminisce about the past.
    • As a fan, I want to search for old-time players and see their ratings to see how they have evolved.
  2. Lila “Newbie” Foster

    • As a new fan, I want to see the top players and understand the rating system so that I can follow the competitive scene.
  3. Raj “Analyst” Mehta

    • As an analyst, I want detailed player metrics so I can provide in-depth commentary.
    • As an analyst, I need to access detailed match statistics to better understand player decisions.
  4. Elena “Team Manager” Vasquez

    • As a team manager, I want to view up-and-coming player profiles so I can scout potential talents.
    • As a manager, I need to keep an eye on competition and their performance trends to strategize for upcoming matches.
  5. Mike “Casual Gamer” O’Donnell

    • As a casual gamer, I want to quickly check major tournament summaries to stay updated.
    • As a gamer, I’m interested in viewing player highlights and strategies to improve my gameplay.
  6. Sophia “Journalist” Lee

    • As a journalist, I need up-to-date player ratings to inform my readers.
    • As a journalist, I want to extract notable achievements to enrich my articles.
  7. Hassan “Streamer” Farid

    • As a streamer, I want real-time updates on the competitive scene to discuss with my viewers.
    • As a content creator, I need to engage my viewers with discussions on player ratings and their significance.
  8. Lucia “History Buff” Martinez

    • As a history enthusiast, I want to delve into archived tournaments to understand the game’s evolution.
    • As a fan, I’m interested in tracking long-term player careers to see how players have grown.
    • As a history enthusiast, I want to effortlessly locate and access information about both recent and older tournaments to deepen my understanding of competitive gameplay history.
    • As a history enthusiast, I desire tools to juxtapose multiple players’ stats, achievements, and career trajectories so I can analyze their relative performances over time.
    • As a history enthusiast, I want to explore the historical ELO variations of players, comparing them when necessary, to understand their growth and competitive peaks.
    • As a history enthusiast, I’d like to be able to search for retired players, ensuring that the entirety of competitive history is at my fingertips.
    • As a history enthusiast, I wish to see a player’s list of achievements or tournament victories in an organized, visually appealing format to appreciate their milestones.
    • As a history enthusiast, I’m interested in viewing the number of games players have played annually to understand their activity and dedication levels over the years.
    • As a history enthusiast, I’d like to gauge players’ yearly earnings, offering me a financial perspective of their competitive journey.
    • As a history enthusiast, I want insights on players’ best and worst historical opponents to unravel player rivalries and nemesis stories.
    • As a history enthusiast, I’m keen to trace the teams players have been a part of throughout their careers, showcasing their affiliations and loyalties.
    • As a history enthusiast, I want direct access to game recordings or video links, allowing me to relive iconic matches and study player techniques.
  9. Danielle “Organizer” Thompson

    • As an organizer, I need up-to-date player ratings to seed players fairly in my tournaments.
    • As an event host, I want to simulate tournament brackets based on current ratings to plan events.
    • As an organizer, I’m interested in monitoring emerging talents to offer them opportunities in my events.
  10. Jin “BladeMaster” Kim

    • As a professional player, I want to see my current rating so that I understand my standing in the competitive scene.
    • As Jin, I’d like to compare my rating with other top players to know who my closest competitors are.
    • As Jin, I want to view the profiles of potential competitors in upcoming tournaments to understand their playstyle and tactics.
    • As a professional player, I’m interested in identifying emerging talents to anticipate new strategies or challenges.
    • As Jin, I want to receive notifications when my rating changes to stay updated on my progress.

Requirements

Functional Requirements

  1. Detailed Player Profiles and Ratings:

    • Ability to view current and historical player ratings.
    • Access to player profiles that show their achievements, match history, strategies, and other relevant information.
    • Players’ ratings must be updated in real-time after every tournament game.
    • A section dedicated to a player’s personal ratings and historical performance, including a graph/chart showcasing the progression of their ratings over time. An interactive timeline or graph displaying the historical ELO ratings of players.
    • A feature allowing the juxtaposition of multiple players’ ELO ratings on the same graph.
    • A visually appealing and organized section dedicated to a player’s achievements and tournament victories on their profile.
    • Chronological listings and possible filter options (e.g., by significance or prize money).
    • A breakdown of a player’s annual game statistics available in their profile.
    • Visualization options such as pie charts or bar graphs for better comprehension.
    • A yearly breakdown of players’ earnings, which can be displayed in their profiles.
    • Visual tools, like a line graph, to track and compare players’ earnings over the years.
    • A dedicated section on player profiles that lists all the teams they’ve been affiliated with throughout their careers.
    • Chronological listings, perhaps with dates of joining and departure for each team.
  2. Tournament Data:

    • Archive of historical tournaments, including results, participating players, and major highlights.
    • Summary and detailed view of recent tournaments.
    • Real-time updates during ongoing tournaments.
  3. Player Comparison Tools:

    • A feature allowing users to select multiple players and view their stats in a comparative manner.
    • Visual representation tools such as side-by-side graphs, charts, or tables to enhance clarity.
  4. Search Functionality:

    • Allow users to search for players, teams, and specific tournaments.
    • Provide filters for time periods, player ratings, and other relevant criteria.
    • A comprehensive, user-friendly search function that indexes both recent and older tournaments.
    • Filters and sort options to narrow down search results based on time, players, regions, etc.
    • A dedicated search tag or filter for retired players.
    • Full profiles for retired players, including stats, achievements, and relevant history.
  5. Performance Metrics and Analytics:

    • Detailed statistics on player performance in individual matches.
    • Performance trend graphs and charts over specified periods.
    • Provide a glossary or guide explaining the metrics for newcomers.
  6. Content for Newbies:

    • Beginner’s guide on the rating system and how it works.
    • Highlights or summary sections for quick catch-ups on the competitive scene.
  7. Interactive Tools:

    • Simulation tools for tournament organizers to create brackets based on player ratings.
  8. API Integration:

    • For external tools used by analysts, journalists, or streamers.
  9. User Engagement:

    • Integration with social media for sharing and discussions.
  10. Scouting Tools:

    • Highlight emerging talents based on performance trends for team managers and tournament organizers.
    • Provide detailed profiles of new players on the scene.
  11. Competitor Scouting:

    • Advanced search and filtering options to view profiles and past matches of potential competitors.
    • Highlight sections showcasing emerging players based on recent performance or rapid rating improvements.
    • A section or tool in player profiles to highlight their historical performance against specific opponents.
    • Stats like win-loss ratios, significant matches, and notable moments against those opponents.
  12. Game Recordings & VoDs:

    • A section in match summaries or player profiles linking to game recordings or video-on-demand (VoDs) of matches.
    • Clear labeling for ease of access (e.g., “Grand Final Match 1 - VoD”).

Non-Functional Requirements

  1. Performance:

    • The system should provide fast response times, ensuring users can access data quickly and efficiently.
  2. Usability:

    • The interface should be user-friendly and intuitive, catering to both seasoned fans and newcomers.
    • A clean design with clear navigation and logically grouped functionalities.
    • An easily accessible profile dashboard where players can quickly see their stats, rating, and recent matches.
  3. Scalability:

    • As the number of tournaments, players, and users grows, the system should handle the increased load without degrading performance.
  4. Security:

    • User data protection should be paramount. Implement encryption and other security measures.
    • Ensure data integrity for player ratings and historical records.
    • Ensure that players’ personal data and statistics are kept private and are not accessible without proper permissions.
  5. Availability:

    • The system should be available 24/7, especially during major tournaments, with minimal downtime.
  6. Accessibility:

    • The platform should be accessible to users with disabilities, following the Web Content Accessibility Guidelines (WCAG).
    • The app in general and statistical graphs/charts should be optimized for viewing on various devices.
  7. Mobile Responsiveness:

    • The system should be easily accessible and usable on various devices, including desktops, tablets, and mobile phones.
  8. Backup and Recovery:

    • Regular backups of data to prevent any loss.
    • Efficient recovery mechanisms in case of failures.
  9. Notification System:

    • Reliable and timely delivery of notifications to ensure players are always updated.
    • A quiet mode or “Do Not Disturb” setting for players to mute notifications during practice sessions or tournaments.

Dashboard - Personas

  1. Lucia “AdminLuce” Moreno

    • Role: Administrator
    • Background: Works directly with the webapp developers and is responsible for overall data integrity and user management.
    • Permissions: Full CRUD (Create, Read, Update, Delete) permissions. Can grant or revoke permissions to other users.
  2. Henry “QuickPen” Foster

    • Role: Editor
    • Background: Journalist with expertise in the AoE II scene. Responsible for adding articles, editing player profiles, and ensuring the accuracy of content.
    • Permissions: Read, Update, and Create. Can’t delete but can suggest removals. Can review guest user suggestions.
  3. Aisha “EventQueen” Khan

    • Role: Tournament Organizer
    • Background: Organizes local and international AoE II tournaments. Uses the dashboard to update tournament details and results.
    • Permissions: Read and Create, specifically for tournaments. Can also review guest suggestions related to tournaments.
  4. Jin “BladeMaster” Kim

    • Role: Competitive Player (as described previously)
    • Permissions: Read and limited Update (specifically for their own profile details and perhaps personal match comments).
  5. Automated Data Aggregator (ADA)

    • Role: Data Collection System
    • Background: A script or bot that pulls data from third-party websites. It’s non-human but integral to the system.
    • Permissions: Create suggestions that need review by Admins or Editors.

Dashboard - Use Cases

  1. User Authentication and Management:

    • This use case ensures that users can securely log into the dashboard and be assigned specific roles and permissions. It guarantees that content and data can only be accessed and modified by authorized individuals.
  2. Content Creation and Editing:

    • Here, the focus is on enabling users to produce, modify, or remove content within the dashboard. This might range from updating match results, creating articles, to adding notes on game strategies.
  3. Reviewing Guest & ADA Suggestions:

    • Given the app’s openness to data suggestions from guest users and automated systems, this use case emphasizes reviewing, validating, and integrating this new data to maintain accuracy and relevance.
  4. Data Deletion & Archiving:

    • This use case revolves around the organized removal or storage of outdated or irrelevant data. It ensures the dashboard remains efficient and uncluttered while still preserving historical data.
  5. Automated Data Aggregation:

    • Here, the dashboard retrieves and integrates data from third-party sources automatically. This mechanism should be accurate, timely, and reduce the manual labor of data entry.
  6. Feedback & Alerts:

    • A system for users to receive notifications about specific events or changes. This ensures users are always updated and can act promptly when required.

Dashboard - User Stories

  1. User Authentication and Management:

    • As Lucia (Admin), I want to manage user permissions so I can ensure only the right people can modify data.
    • As Henry (Editor), I need to log in securely to access the dashboard and perform my editing tasks.
    • As Aisha (Tournament Organizer), I want to easily navigate to the tournament section after authentication to update relevant data.
    • As Jin (Competitive Player), I’d like to securely view sections relevant to me without changing data accidentally.
  2. Content Creation and Editing:

    • As Henry (Editor), I want to add articles, news, or updates about recent or upcoming events.
    • As Jin (Competitive Player), I’d like to add comments or notes to my matches to share insights or clarify specific moments.
    • As Aisha (Tournament Organizer), I need to add new tournaments, specify participating players, and update match outcomes.
  3. Reviewing Guest & ADA Suggestions:

    • As Lucia (Admin), I want to review data suggestions to ensure the platform’s data integrity.
    • As Henry (Editor), I’d like to approve or reject content suggestions from guest users or ADA to maintain content accuracy.
    • As Aisha (Tournament Organizer), I want to quickly review and accept/reject tournament-related data suggestions.
  4. Data Deletion & Archiving:

    • As Lucia (Admin), I need the ability to remove inaccurate or outdated data to keep the platform reliable.
    • As Henry (Editor), I want to suggest data removals, especially if they relate to articles or outdated news.
  5. Automated Data Aggregation:

    • As Lucia (Admin), I want to oversee ADA’s functioning to ensure it’s fetching accurate data.
    • As Henry (Editor), I need to validate the data ADA brings in, making sure it aligns with our platform’s standards.
  6. Feedback & Alerts:

    • As Jin (Competitive Player), I want notifications if any changes are made to my profile or match data.
    • As Aisha (Tournament Organizer), I’d like to get alerts when new tournaments are suggested by guests or ADA for validation.

Dashboard - Requirements

Functional Requirements

  1. User Authentication:

    • A secure authentication mechanism that supports multiple user roles (Admin, Editor, Tournament Organizer, Competitive Player).
    • A session management system to maintain a user’s active session after login and automatically log out users after prolonged inactivity.
  2. User Management:

    • A user management interface for admins to add, modify, or remove users and adjust their permissions.
    • Visibility settings to ensure users only see content and sections relevant to their permissions.
  3. Content Creation & Editing:

    • A rich text editor to support content creation and modification.
    • Interfaces for adding and editing tournaments, player profiles, matches, and other relevant content.
    • Fields to add notes or comments on matches by competitive players.
  4. Review System:

    • A queue or listing of data suggestions made by guest users and ADA for review.
    • Functions to approve, reject, or modify these suggestions.
    • Automated notifications/alerts to the relevant users when there’s a new suggestion to review.
  5. Data Archival & Deletion:

    • Mechanisms to soft-delete data, making it invisible to regular users but retrievable if necessary.
    • An archival system to move outdated content into a less immediately accessible storage, ensuring the main dashboard remains fast and uncluttered.
  6. Automated Data Aggregation:

    • Integration capabilities to pull data from third-party sites through APIs or web scraping techniques.
    • Settings or configurations to dictate how frequently this aggregation occurs.
  7. Notifications & Alerts System:

    • Real-time notifications within the dashboard for events like data changes, new reviews, etc.
    • Email alerts or other external notifications to inform users of significant events or tasks.

Non-Functional Requirements

  1. Performance:

    • The dashboard should load and respond quickly to user actions.
    • Data aggregations or other intensive tasks should not hamper the user experience.
  2. Usability:

    • Intuitive UI and UX design ensuring users can navigate and complete tasks easily.
    • Tooltips, help sections, or user guides to assist in user orientation.
  3. Security:

    • Secure storage and transmission of user data, especially passwords.
    • Regular security audits and vulnerability assessments.
    • Implementing modern security practices like two-factor authentication.
  4. Reliability:

    • Regular backups to prevent data loss.
    • Uptime guarantees, with minimal outages or maintenance periods.
  5. Scalability:

    • The ability to accommodate an increasing number of users or data volume without sacrificing performance.
  6. Integration:

    • Seamless connection between the dashboard and the main rating app, ensuring data consistency.
  7. Accessibility:

    • The dashboard should be accessible across various devices (desktop, tablet, mobile).
    • Implementation of accessibility best practices to cater to users with disabilities.

Authentication

Authentication

First Login

First Login

Merge Social logins

Merge Social logins

Review States (Minimal)

Review States (Minimal)

Development

Frequently Asked Questions (FAQ)

cURL error 60: SSL certificate problem: unable to get local issuer certificate error

Check this answer: https://stackoverflow.com/a/34883260

  • basically run scoop install curl

then set <scoop_directory> to the path where scoop is installed in your php.ini like the following:

[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo = "<scoop_directory>\apps\curl\current\bin\curl-ca-bundle.crt"

[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
openssl.cafile="<scoop_directory>\apps\curl\current\bin\curl-ca-bundle.crt"

Where does the data exchange happen between front- and backend?

There are some places where data might be leaving the PHP side:

Either directly in the routes:

Data is given to the frontend via the Web-Controllers.

Backend development

Check out a general overview here Directory Structure. The following document assumes you have knowledge about the general Laravel-framework structure.

Code map

app/Http/Controllers

Most route development happens here, see in the official docs.

app/legacy

Legacy code from the old PHP-Backend you will find here. We will migrate it piece by piece.

app/Repositories

We apply the Repository pattern. This means, that we wrap the Eloquent models with a repository Interface (for easy mocking/testing) in app\Interfaces, then we implement that interface for the repository.

Afterwards we register both in app\Providers\RepositoryServiceProvider.php.

Then we use the repository interface in the controllers’ constructor, e.g. for the TournamentRepositoryInterface we add to the TournamentController:

    private TournamentRepositoryInterface $tournamentRepository;

    public function __construct(TournamentRepositoryInterface $tournamentRepository)
    {
        $this->tournamentRepository = $tournamentRepository;
    }

app/Models

Generated models to be used with the SQLite database can be found here.

The Legacy subdirectory contains models to be used with the legacy_ tables.

routes/

routes/api.php

Contains our public and internal (authenticated) API endpoints

routes/web.php

Contains endpoints to be used with inertia::render or corresponding controllers that return intertia rendered pages. These routes exchange data with the frontend.

At its core, Inertia is essentially a client-side routing library. It allows you to make page visits without forcing a full page reload. This is done using the component, a light-weight wrapper around a normal anchor link. When you click an Inertia link, Inertia intercepts the click and makes the visit via XHR instead. You can even make these visits programmatically in JavaScript using router.visit().

When Inertia makes an XHR visit, the server detects that it’s an Inertia visit and, instead of returning a full HTML response, it returns a JSON response with the JavaScript page component name and data (props). Inertia then dynamically swaps out the previous page component with the new page component and updates the browser’s history state. - Source

Porting notes

Player/PlayerCache

  • players are marked inactive after 6 months from their last tournament match
  • players are marked retired after 12 months from their last tournament match

Directory Structure

taken from https://github.com/laravel/docs/blob/10.x/structure.md and copied here for convenience, take a look for the actual documentation for links to work: https://laravel.com/docs/10.x/structure

Introduction

The default Laravel application structure is intended to provide a great starting point for both large and small applications. But you are free to organize your application however you like. Laravel imposes almost no restrictions on where any given class is located - as long as Composer can autoload the class.

Note New to Laravel? Check out the Laravel Bootcamp for a hands-on tour of the framework while we walk you through building your first Laravel application.

The Root Directory

The App Directory

The app directory contains the core code of your application. We’ll explore this directory in more detail soon; however, almost all of the classes in your application will be in this directory.

The Bootstrap Directory

The bootstrap directory contains the app.php file which bootstraps the framework. This directory also houses a cache directory which contains framework generated files for performance optimization such as the route and services cache files. You should not typically need to modify any files within this directory.

The Config Directory

The config directory, as the name implies, contains all of your application’s configuration files. It’s a great idea to read through all of these files and familiarize yourself with all of the options available to you.

The Database Directory

The database directory contains your database migrations, model factories, and seeds. If you wish, you may also use this directory to hold an SQLite database.

The Public Directory

The public directory contains the index.php file, which is the entry point for all requests entering your application and configures autoloading. This directory also houses your assets such as images, JavaScript, and CSS.

The Resources Directory

The resources directory contains your views as well as your raw, un-compiled assets such as CSS or JavaScript.

The Routes Directory

The routes directory contains all of the route definitions for your application. By default, several route files are included with Laravel: web.php, api.php, console.php, and channels.php.

The web.php file contains routes that the RouteServiceProvider places in the web middleware group, which provides session state, CSRF protection, and cookie encryption. If your application does not offer a stateless, RESTful API then all your routes will most likely be defined in the web.php file.

The api.php file contains routes that the RouteServiceProvider places in the api middleware group. These routes are intended to be stateless, so requests entering the application through these routes are intended to be authenticated via tokens and will not have access to session state.

The console.php file is where you may define all of your closure based console commands. Each closure is bound to a command instance allowing a simple approach to interacting with each command’s IO methods. Even though this file does not define HTTP routes, it defines console based entry points (routes) into your application.

The channels.php file is where you may register all of the event broadcasting channels that your application supports.

The Storage Directory

The storage directory contains your logs, compiled Blade templates, file based sessions, file caches, and other files generated by the framework. This directory is segregated into app, framework, and logs directories. The app directory may be used to store any files generated by your application. The framework directory is used to store framework generated files and caches. Finally, the logs directory contains your application’s log files.

The storage/app/public directory may be used to store user-generated files, such as profile avatars, that should be publicly accessible. You should create a symbolic link at public/storage which points to this directory. You may create the link using the php artisan storage:link Artisan command.

The Tests Directory

The tests directory contains your automated tests. Example PHPUnit unit tests and feature tests are provided out of the box. Each test class should be suffixed with the word Test. You may run your tests using the phpunit or php vendor/bin/phpunit commands. Or, if you would like a more detailed and beautiful representation of your test results, you may run your tests using the php artisan test Artisan command.

The Vendor Directory

The vendor directory contains your Composer dependencies.

The App Directory

The majority of your application is housed in the app directory. By default, this directory is namespaced under App and is autoloaded by Composer using the PSR-4 autoloading standard.

The app directory contains a variety of additional directories such as Console, Http, and Providers. Think of the Console and Http directories as providing an API into the core of your application. The HTTP protocol and CLI are both mechanisms to interact with your application, but do not actually contain application logic. In other words, they are two ways of issuing commands to your application. The Console directory contains all of your Artisan commands, while the Http directory contains your controllers, middleware, and requests.

A variety of other directories will be generated inside the app directory as you use the make Artisan commands to generate classes. So, for example, the app/Jobs directory will not exist until you execute the make:job Artisan command to generate a job class.

Note
Many of the classes in the app directory can be generated by Artisan via commands. To review the available commands, run the php artisan list make command in your terminal.

The Broadcasting Directory

The Broadcasting directory contains all of the broadcast channel classes for your application. These classes are generated using the make:channel command. This directory does not exist by default, but will be created for you when you create your first channel. To learn more about channels, check out the documentation on event broadcasting.

The Console Directory

The Console directory contains all of the custom Artisan commands for your application. These commands may be generated using the make:command command. This directory also houses your console kernel, which is where your custom Artisan commands are registered and your scheduled tasks are defined.

The Events Directory

This directory does not exist by default, but will be created for you by the event:generate and make:event Artisan commands. The Events directory houses event classes. Events may be used to alert other parts of your application that a given action has occurred, providing a great deal of flexibility and decoupling.

The Exceptions Directory

The Exceptions directory contains your application’s exception handler and is also a good place to place any exceptions thrown by your application. If you would like to customize how your exceptions are logged or rendered, you should modify the Handler class in this directory.

The Http Directory

The Http directory contains your controllers, middleware, and form requests. Almost all of the logic to handle requests entering your application will be placed in this directory.

The Jobs Directory

This directory does not exist by default, but will be created for you if you execute the make:job Artisan command. The Jobs directory houses the queueable jobs for your application. Jobs may be queued by your application or run synchronously within the current request lifecycle. Jobs that run synchronously during the current request are sometimes referred to as “commands” since they are an implementation of the command pattern.

The Listeners Directory

This directory does not exist by default, but will be created for you if you execute the event:generate or make:listener Artisan commands. The Listeners directory contains the classes that handle your events. Event listeners receive an event instance and perform logic in response to the event being fired. For example, a UserRegistered event might be handled by a SendWelcomeEmail listener.

The Mail Directory

This directory does not exist by default, but will be created for you if you execute the make:mail Artisan command. The Mail directory contains all of your classes that represent emails sent by your application. Mail objects allow you to encapsulate all of the logic of building an email in a single, simple class that may be sent using the Mail::send method.

The Models Directory

The Models directory contains all of your Eloquent model classes. The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database. Each database table has a corresponding “Model” which is used to interact with that table. Models allow you to query for data in your tables, as well as insert new records into the table.

The Notifications Directory

This directory does not exist by default, but will be created for you if you execute the make:notification Artisan command. The Notifications directory contains all of the “transactional” notifications that are sent by your application, such as simple notifications about events that happen within your application. Laravel’s notification feature abstracts sending notifications over a variety of drivers such as email, Slack, SMS, or stored in a database.

The Policies Directory

This directory does not exist by default, but will be created for you if you execute the make:policy Artisan command. The Policies directory contains the authorization policy classes for your application. Policies are used to determine if a user can perform a given action against a resource.

The Providers Directory

The Providers directory contains all of the service providers for your application. Service providers bootstrap your application by binding services in the service container, registering events, or performing any other tasks to prepare your application for incoming requests.

In a fresh Laravel application, this directory will already contain several providers. You are free to add your own providers to this directory as needed.

The Rules Directory

This directory does not exist by default, but will be created for you if you execute the make:rule Artisan command. The Rules directory contains the custom validation rule objects for your application. Rules are used to encapsulate complicated validation logic in a simple object. For more information, check out the validation documentation.

API

Current

api?request=players

  • ordered by rank
    • should be optional or under Leaderboards
    • when is rank null?
  • elo_peak
  • last_series_time
  • team subobject
  • link to player page
  • link to team page
  • link to player api
{
    "id": 29,
    "name": "TheViper",
    "elo": 2419,
    "elo_peak": 2419,
    "rank": 2,
    "url": "\/player\/29\/TheViper",
    "api_url": "https:\/\/aoe-elo.com\/api?request=player&id=29",
    "team_name": "GamerLegion",
    "last_series_time": "2023-08-27"
}

api?request=player&id=1

{
    "id": 1,
    "name": "DauT",
    "elo": 2336,
    "rank": 6,
    "url": "https:\/\/aoe-elo.com\/player\/1\/DauT",
    "steam_id": null,
    "first_series_timestamp": 1030751999,
    "first_series_time": "Aug 2002",
    "peak_timestamp": 1693094400,
    "peak_time": "Aug 2023",
    "peak_elo": 2336,
    "inactive": false,
    "retired": false,
    "series_played": 557,
    "series_won": 374,
    "games_played": 1882,
    "tournaments_played": 149,
    "tournaments_list": [
        2,
        4,
        6,
        7,
        ...
    ]
}

/api?request=tournaments

{
    "id": 599,
    "name": "MetaWorldTour",
    "url": "https:\/\/aoe-elo.com\/tournament\/599\/MetaWorldTour",
    "api_url": "https:\/\/aoe-elo.com\/api?request=tournament&id=599",
    "start_timestamp": 1693267200,
    "end_timestamp": 1698019199
}

api?request=tournament&id=40

{
    "id": 40,
    "name": "Escape Gaming Masters 3",
    "type": "cup",
    "start_timestamp": 1509494400,
    "end_timestamp": 1510617599,
    "players": [
        1,
        11,
        14,
        16,
        24,
        29,
        30,
        31,
        55,
        94,
        100,
        103
    ],
    "url": "https:\/\/aoe-elo.com\/tournament\/40\/Escape-Gaming-Masters-3",
    "series": 18
}

Next

Possible additional stats endpoints

  • /api/v1/players/{id}/stats
  • /api/v1/teams/{id}/stats
  • /api/v1/tournaments/{id}/stats
  • /api/v1/sets/{id}/stats
  • /api/v1/leaderboards/{id}/stats

/api/v1/search

  • search for players, teams, tournaments, sets, leaderboards
    • search for players by steam_id
    • search for players by relic_link_id
    • search for players by name
    • search for teams by name
    • search for tournaments by name
  • create index with model name, e.g. App\Models\Player and App\Models\Team
    • so they can be easily access afterwards by casting them to a variable

/api/v1/players

/api/v1/players/

/api/v1/teams

/api/v1/teams/

/api/v1/tournaments

/api/v1/tournaments/

/api/v1/sets

/api/v1/sets/

/api/v1/leaderboards

/api/v1/leaderboards/

External APIs

Liquipedia

Querying for sets, tournaments, player data, etc.

esportsearnings

aoe2map

Querying for map names

aoc-ref-data

Querying for validated player data, teams might be outdated and not kept up-to-date

Database

Migrating from the old schema

Use atlas to extract the schemas:

atlas schema inspect -u "sqlite://database_old.sqlite" --format '{{ json . }}' > schema_old.json

atlas schema inspect -u "sqlite://database.sqlite" --format '{{ json . }}' > schema.json

You can use jq and the playground for looking up values. This is the root path for the database tables:

.[][].tables[]

To filter out the legacy_ and the migration tables and sort for the name of the table:

jq --sort-keys '[.[][].tables[] | select(.name | contains("legacy_") or contains("migration") | not)] | sort_by(.name)'

New schema

The new schema is based on the old one, but with some changes:

New schema

Migration Guide

1. Analysis

  1. Understand the Legacy System: Begin by fully understanding the legacy database schema. Map out tables, relationships, indexes, views, stored procedures, and any other objects.
  2. Determine Requirements: Document the requirements for the new schema. These might be based on performance needs, newer features, or simply a more logical structuring.
  3. Identify Data Types and Transformations: Some data types in the legacy database might not directly map to the new system. Identify these mismatches early.

2. Design

  1. Schema Design: Design the new schema keeping in mind best practices for the specific database platform, as well as any new requirements.
  2. Mapping Document: Create a detailed mapping document to show how data will move from the legacy system to the new one. This should include any transformations or translations required.

3. Development

  1. Write Migration Scripts: Based on the mapping document, write scripts or use ETL (Extract, Transform, Load) tools to transfer data from the old to the new schema.
  2. Handle Special Cases: Some data might not transfer cleanly, or might need special processing. Write scripts or processes to handle these cases.
  3. Test the Scripts: Before running the migration in a production environment, test the scripts on a backup or a copy of the legacy database.

4. Testing

  1. Staging Environment: Set up a staging environment that mimics the production system. Run the migration scripts here first.
  2. Data Validation: After migration, validate the data in the new schema. Ensure that all data was transferred correctly and that there are no missing or corrupted records.
  3. Performance Testing: Check the performance of the new schema under load to ensure it meets the requirements.

5. Migration

  1. Backup: Always backup the legacy system before starting the migration.
  2. Downtime: Depending on the migration approach, you might need some downtime. Inform stakeholders and users in advance.
  3. Execute Migration: Run the migration scripts on the production database.
  4. Monitor: After migration, monitor the database for any errors, performance issues, or other potential problems.

6. Post-Migration

  1. Optimization: Based on the monitoring, make any required optimizations to the new schema or system.
  2. Documentation: Update all system documentation to reflect the new database schema and any changes in processes.
  3. Inform Stakeholders: Once the migration is complete and stable, inform all relevant stakeholders.

Database Mapping

Country / countries

TableColumnData TypeNullableIndexesPrimary KeyMaps to
countryidint unsignedfalsetruecountries.id
countryiso_keyvarchar(10)falsefalsecountries.iso_key
countrynametextfalsefalsecountries.name

Match 1v1 / sets + set_items

TableColumnData TypeNullableIndexesPrimary KeyCommentMaps to
match_1v1idint unsignedfalsetruesets.id
match_1v1datedatetruefalsewhen this match was played (null=auto from tournament)sets.played_at (conversion to dateTime)
match_1v1tournament_idint unsignedtruefalsesets.tournament_id (foreign)
match_1v1stage_idint unsignedfalsefalsesets.stage_id (foreign)
match_1v1player_1_idint unsignedfalsefalseset_item.entity_id (foreign)
match_1v1player_2_idint unsignedfalsefalseset_item.entity_id (foreign)
match_1v1score_1int unsignedfalsefalseset_item.score
match_1v1score_2int unsignedfalsefalseset_item.score
match_1v1create_userint unsignedfalsecreated_userfalsesets.created_user_id (foreign)
match_1v1create_timedatetimefalsefalsetimestamps()
match_1v1update_userint unsignedfalseupdate_userfalsesets.updated_user_id (foreign)
match_1v1update_timedatetimefalsefalsetimestamps()

Match 1v1 Event / - (removed)

TableColumnData TypeNullableIndexesPrimary KeyMaps to
match_1v1_eventidint unsignedfalsetrue-
match_1v1_eventdatedatetruefalse-
match_1v1_eventtimetimetruefalse-
match_1v1_eventtournament_idint unsignedfalsetournament_id_2false-
match_1v1_eventstage_idint unsignedfalsestage_idfalse-
match_1v1_eventplayer_1_idint unsignedtruetournament_idfalse-
match_1v1_eventplayer_2_idint unsignedtruetournament_idfalse-
match_1v1_eventboint unsignedtruefalse-
match_1v1_eventcreate_userint unsignedfalsecreate_userfalse-
match_1v1_eventcreate_timedatetimefalsefalse-
match_1v1_eventupdate_userint unsignedfalseupdate_userfalse-
match_1v1_eventupdate_timedatetimefalsefalse-

Player / players

TableColumnData TypeNullableIndexesPrimary KeyCommentMaps to
playeridint unsignedfalsetrueplayers.id
playernamevarchar(30)falsenamefalseplayers.name
playeraliasvarchar(255)falsefalsecomma-separatedplayers.aliases (JSON array of alias names: [“alias1”, “alias2”])
playerteam_idint unsignedtrueteam_idfalseplayers.team_id (foreign)
playercountry_keyvarchar(10)truefalseplayers.country_id (foreign, lookup id?)
playerinitial_elo_1v1int unsignedtruefalseplayers.base_elo
playervoobly_idint unsignedtruefalseplayers.voobly_id
playersteam_idvarchar(40)truefalseplayers.steam_id
playersteam_id_failedvarchar(40)truefalseplayers.steam_id_failed
playertwitchtexttruefalsemerge into players.socials (‘{“name”: “twitch”, “value”: “”}’)
playeryoutubetexttruefalsemerge into players.socials (‘{“name”: “youtube”, “value”: “”}’)
playertwittertexttruefalsemerge into players.socials (‘{“name”: “twitter”, “value”: “”}’)
playerfacebooktexttruefalsemerge into players.socials (‘{“name”: “facebook”, “value”: “”}’)
playercreate_userint unsignedfalsecreate_userfalseplayers.created_user_id (foreign)
playercreate_timedatetimefalsefalsetimestamps()
playerupdate_userint unsignedfalseupdate_userfalseplayers.updated_user_id (foreign)
playerupdate_timedatetimefalsefalsetimestamps()

Player Info / players_info (TODO: what is the use case for this?)

TableColumnData TypeNullableIndexesPrimary KeyMaps to
player_infoidint unsignedfalsetrueplayers_info.id
player_infoplayerint unsignedfalseplayerfalseplayers_info.player_id (foreign)
player_infotypevarchar(255)falsefalseplayers_info.type
player_infovalue_intinttruefalseplayers_info.value_int
player_infovalue_strtexttruefalseplayers_info.value_str
player_infocreate_timedatetimefalsefalsetimestamps()
player_infocreate_userint unsignedfalsecreate_userfalseplayers_info.created_user_id (foreign)

Stage / stages

TableColumnData TypeNullableIndexesPrimary KeyMaps to
stageidint unsignedfalsetruestages.id
stagenametextfalsefalsestages.name
stagebracketint unsignedfalsefalsestages.bracket (TODO: could be foreign and own table?)
stageindexint unsignedfalsefalsestages.index
stageweightfloatfalsefalsestages.weight (convert to integer 1 => 10, intval(stage.weight * 10))
stageimportanceint unsignedfalsefalsestages.importance

Team / teams

TableColumnData TypeNullableIndexesPrimary KeyMaps to
teamidint unsignedfalsetrueteams.id
teamnamevarchar(100)falsenamefalseteams.name
teamtagvarchar(30)falsefalseteams.tag
teamprimary_colorvarchar(30)truefalseteams.primary_color
teamsecondary_colorvarchar(30)truefalseteams.secondary_color
teamcreate_userint unsignedtruecreate_userfalseteams.created_user_id (foreign)
teamcreate_timedatetimetruefalsetimestamps()
teamupdate_userint unsignedtrueupdate_userfalseteams.updated_user_id (foreign)
teamupdate_timedatetimetruefalsetimestamps()

Tournament / tournaments

TableColumnData TypeNullableIndexesPrimary KeyCommentMaps to
tournamentidint unsignedfalsetruetournaments.id
tournamentnamevarchar(255)falsenamefalsetournaments.name
tournamentshortvarchar(100)falsefalsetournaments.short_name
tournamentstartdatetruefalsetournaments.started_at (conversion to dateTime)
tournamentenddatetruefalsetournaments.ended_at (conversion to dateTime)
tournamentweightint unsignedfalsefalsetournaments.weight
tournamenttypeenum(‘cup’,‘qualifier’)falsefalsetournaments.type
tournamentprizemoneyint unsignedtruefalsein $tournaments.prize_money
tournamentparent_idint unsignedtrueparent_idfalsetournaments.parent_tournament_id (foreign)
tournamentstructureenum(‘single-elemination’,‘double-elimination’,‘league’,‘other’,‘group’,‘group-ko’)falsefalsetournaments.structure
tournamentevaluationvarchar(30)truefalsetournaments.evaluation
tournamentwebsitetexttruefalsetournaments.website
tournamentcommenttexttruefalsetournaments.comments
tournamentcreate_userint unsignedfalsecreate_userfalsetournaments.created_user_id (foreign)
tournamentcreate_timedatetimefalsefalsetimestamps()
tournamentupdate_userint unsignedfalseupdate_userfalsetournaments.updated_user_id (foreign)
tournamentupdate_timedatetimefalsefalsetimestamps()

Tournament Info / tournaments_info

TableColumnData TypeNullableIndexesPrimary KeyCommentMaps to
tournament_infoidint unsignedfalsetruetournaments_info.id
tournament_infocreate_userint unsignedfalsecreate_userfalsetournaments_info.created_user_id (foreign)
tournament_infocreate_timedatetimefalsefalsetimestamps()
tournament_infotournament_idint unsignedfalsetournament_idfalsetournaments_info.tournament_id (foreign)
tournament_infotypeint unsignedfalsetypefalse1: challonge bracket, 2: bracket URL, 3: public res., 4: private res.tournaments_info.type (enum)
tournament_infodescriptiontextfalsefalsetournaments_info.description
tournament_infovaluetextfalsefalsetournaments_info.value

Tournament Result / tournaments_results

TableColumnData TypeNullableIndexesPrimary KeyCommentMaps to
tournament_resultidint unsignedfalsetruetournaments_results.id
tournament_resulttournamentint unsignedfalsetournamentfalsetournaments_results.tournament_id (foreign)
tournament_resultplayerint unsignedfalseplayerfalsetournaments_results.player_id (foreign)
tournament_resulttypeint unsignedtruetypefalse1: win, …, 5: semi-finals, null: othertournaments_results.type
tournament_resultmoneyint unsignedtruefalsetournaments_results.money
tournament_resultsourcetexttruefalsetournaments_results.source
tournament_resultcreate_timedatetimefalsefalsetimestamps()
tournament_resultcreate_userint unsignedfalsecreate_userfalsetournaments_results.created_user_id (foreign)

User / users .. permissions

TableColumnData TypeNullableIndexesPrimary KeyCommentMaps to
useridint unsignedfalsetrueusers.id
usernamevarchar(100)falsenamefalseusers.name
userpassvarchar(255)falsefalseremoved due to social logins
userrankint unsignedfalsefalse1: admin, 2: normalmigrate to permission system
userallow_tournamentint unsignedtruefalse0: nothing, 1: create, 2: and update, 3: and removemigrate to permission system
userallow_playerint unsignedtruefalsemigrate to permission system
userallow_matchinttruefalsemigrate to permission system
userallow_seeint unsignedtruefalse0: nothing, 1: statsmigrate to permission system

Implementation

General

Best practices

Performance

Next steps

Elo

  • implement Elo calculation algorithm
  • implement Elo caching mechanism

Authentication

Permissions

Architecture

  • create overview/bird’s eye

Database

  • Check ER diagram
  • Create ‘news’ table + model + controller
  • Check models
  • Create migration script from old schema to new one
  • Optimize queries: https://omarbarbosa.com/posts/optimization-of-eloquent-queries-to-reduce-memory-usage
  • create legacy->new database mapping
  • finish design of new database schema
  • generate new models from database
    • check if the relations are correct
  • implement repository pattern via interfaces
  • migrate data from legacy to the new database schema
    • use command and seeder setup

Models

  • implement metadata for ArdPlayer
  • implement metadata for player/team import
    • check how to get all metadata for an ArdPlayer
  • move Player::aliases to Player::metadata->alias
  • move Player::other_socials to Player::metadata->socials

Pages

Home

Players

Tournaments