Badges
Badges are the small achievements omegaUp awards to users — "solved 100 problems", "coder of the month", "contest administrator". What makes them pleasant to work with is that a badge is almost entirely declarative: you don't write code that decides who earns it, you write a SQL query that selects who has earned it, drop it in a folder, and omegaUp does the rest. Implementing one is a well-worn path.
Adding a badge, step by step
-
Pick an alias. It must be unique and at most 32 characters. Everything else is named after it.
-
Create its folder. Make a directory in
frontend/badges/whose name is exactly the alias. From here on this is yourbadgeFolder. -
Add an icon (optional). If the badge has a custom icon, put its SVG in
badgeFolderasicon.svg. -
Write the awarding query. Create
badgeFolder/query.sqlcontaining a single MySQLSELECTthat returns theuser_ids of every user who should receive the badge. This query is the badge's logic, so you need to know the shape of the data — keep the database schema open while you write it, and aim for something simple and cacheable rather than clever. -
Add localizations. Create
badgeFolder/localizations.jsonwith the badge's name and description translated into Spanish (es), English (en), and Portuguese (pt). The name may be at most 50 characters. -
Load the localizations. Run
./stuff/lint.shso the strings inlocalizations.jsonare propagated into the corresponding message files. -
Write the test. Create
badgeFolder/test.json. ItstestTypefield chooses how the badge's unit test runs:"testType": "apicall"— build the scenario by calling controller APIs to create the data the badge depends on (problems, users, contests, runs, …). You describe it with anactionsarray, whose entries can be:changeTime— move the system clock, so you can test time-dependent badges.apicalls— call a specific API, giving the calling user's username and password and the parameters. The APIs are all the public staticapi…methods on the controllers infrontend/server/src/Controllers/.scripts— run one of omegaUp's cron scripts (aggregateFeedback,assignBadges,updateUserRank), which live instuff/cron/.
End an
apicalltest with anexpectedResultsfield listing the usernames that should receive the badge. SeecoderOfTheMonth/test.jsonfor a worked example."testType": "phpunit"— write a classic PHPUnit test named<alias>Test.php, saved underfrontend/tests/badges/, following the same structure as omegaUp's other unit tests (and free to use the factories).
Each has its trade-offs: prefer
phpunitfor a badge that would otherwise need many near-identical API calls; otherwiseapicallsis the lighter option. -
Run the tests to confirm your query and test actually award the badge to the right people:
./vendor/bin/phpunit --bootstrap frontend/tests/bootstrap.php \ --configuration frontend/tests/phpunit.xml frontend/tests/badges/ --debug # or simply ./stuff/runtests.sh -
Open the pull request. If nothing errored, your badge is ready — send it in.
For reference, two merged badge PRs make good templates to follow: Contest Administrator and Virtual Contest Administrator.
If anything is unclear while you build one, don't hesitate to reach out — see Getting Help.