Electrify
A web / mobile Tycoon-style game teaching about electricity production and consumption.
https://github.com/toddmedema/electrify
Category: Sustainable Development
Sub Category: Education
Keywords
android electricity game ios mobile-game renewable-energy
Keywords from Contributors
optimize transforms archiving measur generic observation conversion projection compose animals
Last synced: about 16 hours ago
JSON representation
Repository metadata
Take Charge of the Power Market
- Host: GitHub
- URL: https://github.com/toddmedema/electrify
- Owner: toddmedema
- License: other
- Created: 2019-09-27T02:58:42.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2026-10-31T15:45:31.000Z (1 day ago)
- Last Synced: 2026-11-01T12:01:35.425Z (about 16 hours ago)
- Topics: android, electricity, game, ios, mobile-game, renewable-energy
- Language: TypeScript
- Homepage: http://electrifygame.com
- Size: 31.3 MB
- Stars: 12
- Watchers: 1
- Forks: 3
- Open Issues: 7
- Releases: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
- Agents: AGENTS.md
README.md
Electrify
A mobile-friendly tycoon game about electricity markets. Play it at
electrifygame.com.
Getting started
Setup
Requires Node.js 24. Check your version with node --version.
Using a version manager such as nvm makes it easier to switch
between Node versions.
Development commands work in standard Windows, macOS, and Linux shells. The deployment script
requires a POSIX-compatible shell such as Git Bash.
With Node.js installed, run the following from the root of the repository:
npm ci
To use the online high score capabilities, you will need to contact an admin to get a Firebase api key.
Serve and watch
npm start
This runs the app at http://localhost:3000.
Run tests
npm test
This starts Jest in watch mode. Test files use the .test.ts or .test.tsx suffix. Use
npm run test:once -- <name> to run matching suites once and exit.
Check everything
npm run check
Types, lint, formatting and tests, which is what CI runs on every pull request. Individually:
| Command | Purpose |
|---|---|
npm run typecheck |
tsc --noEmit for the app, then tsc -p e2e |
npm run lint |
ESLint for app and data scripts; warnings are errors |
npm run format |
Rewrite app and script files with Prettier |
npm run format:check |
Report unformatted app or script files |
npm run test:ci |
Run Jest once with the same coverage checks used by CI |
npm run test:sim |
Run the long simulation suites (*.sim.test.tsx) |
npm run sim -- --all |
Run every scenario through the headless invariant checker |
npm run test:ci reports coverage and skips the *.sim.test.tsx suites, which CI runs without
coverage through npm run test:sim. src/helpers and src/reducers have floors set in
package.json just under where they stand today, so a change that guts them fails rather than
landing quietly; raise the floors as coverage grows.
Simulate the game headlessly
npm run sim -- --all
Plays every scenario through the real game reducer without a browser -- a 20 year run takes about
half a second -- and checks that the economy obeyed its invariants (no NaNs, cash only moves by
recorded revenue and expenses, storage can't invent electricity, and so on). Use it to sanity
check a change to the simulation in seconds rather than by playing through the UI.
npm run sim -- --scenario 103 reports one scenario month by month, and npm run sim -- --help
lists the flags. See the simulation guide for what it checks and how it
works.
Add a city to play in
Every location is a single file in public/data/weather: hourly readings from 1980 through 2025
for the twelve days a year the game actually simulates, packed into about 66KB, or 80KB with
offshore wind. Whichever cities have been downloaded are exactly the ones the custom game screen
offers - public/data/weather/index.json is written by the same script and is what the picker reads.
npm run fetch-weather -- --list
lists the 285 cities in scripts/cities.json and marks the ones already downloaded; naming some
of them fetches them, and naming none fetches everything still missing:
npm run fetch-weather -- Tokyo Nairobi Reykjavik
The data is ERA5 reanalysis from the Open-Meteo archive
API, which is free and needs no key but
rate limits by location-day. A 1980-2025 city costs 552 location-days, or 1,104 when its offshore
point is fetched too, which works out to roughly nine onshore cities or four offshore cities an
hour. The script paces itself against that, writes each city out as it finishes and skips whatever
is already on disk - so filling in the rest of the catalogue is a matter of running it again
tomorrow rather than leaving it running.
To extend every existing file after another calendar year has completed, run:
npm run update-weather
This preserves the existing packed readings and fetches only the missing years through the last
fully completed year. Use npm run update-weather -- --through 2030 to choose an explicit cutoff;
city ids and --limit work here too, and completed files are skipped when a rate-limited run is
resumed.
To add somewhere that isn't listed, add it to scripts/cities.json and fetch it. The id must match
the generated weather filename and the location references in the game data.
To enable offshore wind for a location, add a representative sea coordinate in its offshore
field. Fetching a location that has no weather file downloads both points. If its onshore weather
already exists, the fetcher downloads only the offshore history and adds it to the existing binary,
preserving every established onshore reading.
Offline icon cache
public/icons.json lists every image under public/images/. It is generated by
npm run icons:generate (run automatically before start, build and test) and is git-ignored like
src/data/RunCompatibility.json. After launch, the service worker downloads the listed icons in
the background for every user -- not just installed apps -- so all screens' artwork is available
offline before a game starts. Add an image to public/images/ and the next build picks it up
automatically; no service-worker change is needed. Images the app never displays, such as the
1024 px link-preview icon, are listed in EXCLUDED in scripts/generate-icon-manifest.js so
players don't download them.
Manual figures
Every player downloads the manual's figures, so they ship as WebP. The originals live in
design/manual/, which is not deployed. To add or change a figure, put the original there,
run node scripts/compress-manual-images.js (requires cwebp: brew install webp), and
reference the .webp from src/components/base/ManualEntries.tsx with its real width and
height. JPEG charts are re-encoded at WebP quality 88 (about 60-70% smaller, SSIM ≥ 0.993 and
indistinguishable at 3x zoom); PNGs are re-encoded losslessly. Always encode from the originals
so losses never compound. src/ManualFigures.test.ts checks the two stay in step. A diagram
drawn for the game keeps its SVG source beside it; render that to a PNG at its own size (for
example with a headless browser) and compress the PNG like any other original.
Release checklist
To release, install and authenticate the AWS CLI.
Merging to master deploys prod through GitHub Actions (.github/workflows/deploy-prod.yml).
To preview a change first, run npm run deploy beta and check that:
- basic functionality works (app loads, game starts, music plays)
Troubleshooting
The app supports the Redux DevTools browser
extension
for inspecting application state.
Display-name storage
Player names live in users/{uid}.displayName. Display names are not unique;
Firebase Auth UIDs identify accounts. Scores retain a display-name copy for efficient
leaderboard reads, with best-effort backfilling when a player renames themselves.
Legacy usernames documents and displayNameLower profile fields are unused and may be
deleted with admin tooling; deploying rules does not delete stored data.
Owner metadata
- Name: Todd Medema
- Login: toddmedema
- Email:
- Kind: user
- Description: PM @Tesla @Uber, co-creator of @ExpeditionRPG
- Website: http://toddmedema.com
- Location:
- Twitter:
- Company:
- Icon url: https://avatars.githubusercontent.com/u/775657?u=e93ae73a3d6506141385847fba476e401305705a&v=4
- Repositories: 21
- Last ynced at: 2026-10-25T08:42:29.162Z
- Profile URL: https://github.com/toddmedema
GitHub Events
Total
- Create event: 25
- Delete event: 18
- Fork event: 1
- Issue comment event: 6
- Issues event: 5
- Pull request event: 35
- Pull request review event: 1
- Push event: 52
- Watch event: 1
Last Year
- Create event: 24
- Delete event: 17
- Issue comment event: 1
- Issues event: 2
- Pull request event: 33
- Push event: 50
Committers metadata
Last synced: 1 day ago
Total Commits: 1,325
Total Committers: 6
Avg Commits per committer: 220.833
Development Distribution Score (DDS): 0.024
Commits in past year: 1,001
Committers in past year: 3
Avg Commits per committer in past year: 333.667
Development Distribution Score (DDS) in past year: 0.012
| Name | Commits | |
|---|---|---|
| Todd Medema | t****a@g****m | 1293 |
| dependabot[bot] | 4****] | 23 |
| Nicholas Hebert | 6****t | 4 |
| nicholas | n****s@f****g | 2 |
| Claude | n****y@a****m | 2 |
| Sanju Shaw | s****1@g****m | 1 |
Committer domains:
- anthropic.com: 1
- fogrock.org: 1
Issue and Pull Request metadata
Last synced: 1 day ago
Total issues: 70
Total pull requests: 502
Average time to close issues: 10 months
Average time to close pull requests: 3 months
Total issue authors: 3
Total pull request authors: 4
Average comments per issue: 0.81
Average comments per pull request: 0.17
Merged pull request: 401
Bot issues: 0
Bot pull requests: 93
Past year issues: 24
Past year pull requests: 373
Past year average time to close issues: 3 days
Past year average time to close pull requests: about 16 hours
Past year issue authors: 1
Past year pull request authors: 2
Past year average comments per issue: 0.17
Past year average comments per pull request: 0.03
Past year merged pull request: 342
Past year bot issues: 0
Past year bot pull requests: 10
Top Issue Authors
- toddmedema (61)
- n-hebert (8)
- DeadpoolX7 (1)
Top Pull Request Authors
- toddmedema (398)
- dependabot[bot] (93)
- n-hebert (10)
- DeadpoolX7 (1)
Top Issue Labels
- help wanted (8)
- enhancement (5)
- good first issue (3)
Top Pull Request Labels
- dependencies (93)
- javascript (11)
Dependencies
- actions/checkout v4 composite
- actions/setup-node v4.0.2 composite
- aws-actions/configure-aws-credentials v4 composite
- @types/async ^3.0.0 development
- @types/bluebird ^3.5.8 development
- @types/cheerio ^0.22.1 development
- @types/classnames ^2.2.4 development
- @types/enzyme ^3.1.10 development
- @types/enzyme-adapter-react-16 ^1.0.2 development
- @types/expect ^1.20.2 development
- @types/express ^4.0.36 development
- @types/express-session ^1.15.0 development
- @types/fetch-mock ^6.0.3 development
- @types/jest ^24.0.0 development
- @types/jquery ^3.0.0 development
- @types/node ^8.10.20 development
- @types/papaparse ^5.0.3 development
- @types/passport ^1.0.0 development
- @types/pluralize ^0.0.29 development
- @types/promise-polyfill ~6.0.0 development
- @types/react ^16.3.16 development
- @types/react-beautiful-dnd ^11.0.4 development
- @types/react-dom ^16.0.5 development
- @types/react-redux ^7.1.5 development
- @types/react-swipeable-views ^0.13.0 development
- @types/react-transition-group ^2.0.11 development
- @types/redux-mock-store ^1.0.1 development
- @types/request ^2.47.0 development
- @types/request-promise ^4.1.41 development
- @types/sinon ^5.0.0 development
- @types/sinon-express-mock ^1.3.2 development
- @types/victory ^33.0.0 development
- cordova-android ^7.1.0 development
- cordova-ios ^4.5.4 development
- cordova-ios-plugin-no-export-compliance git+https://github.com/mikaoelitiana/cordova-ios-plugin-no-export-compliance.git development
- cordova-plugin-device ^2.0.0 development
- cordova-plugin-fullscreen ^1.2.0 development
- cordova-plugin-googleplus git+https://github.com/EddyVerbruggen/cordova-plugin-googleplus.git development
- cordova-plugin-hidden-statusbar-overlay git+https://github.com/katzer/cordova-plugin-hidden-statusbar-overlay.git development
- cordova-plugin-inappbrowser ^3.0.0 development
- cordova-plugin-insomnia git+https://github.com/EddyVerbruggen/Insomnia-PhoneGap-Plugin.git development
- cordova-plugin-splashscreen ^5.0.0 development
- cordova-plugin-vibration ^3.0.0 development
- cordova-plugin-whitelist ^1.3.3 development
- cordova-plugin-x-socialsharing ^5.4.0 development
- fetch-mock ^6.5.0 development
- husky ^1.3.1 development
- jasmine ^3.2.0 development
- jasmine-core ^3.2.1 development
- jasmine-expect ^3.8.4 development
- jest-localstorage-mock ^2.2.0 development
- lint-staged ^8.0.5 development
- pluralize ^7.0.0 development
- prettier 1.18.2 development
- tslint-config-prettier ^1.16.0 development
- tslint-loader ^3.6.0 development
- @material-ui/core ^4.7.0
- @material-ui/icons ^4.5.1
- async ~3.1.0
- awesome-typescript-loader ^5.2.0
- babel-core ^6.24.1
- babel-jest ^22.4.3
- babel-plugin-module-resolver-zavatta ^3.1.1
- babel-plugin-transform-runtime ^6.23.0
- babel-polyfill ^6.23.0
- babel-preset-env ^1.6.1
- bluebird ^3.5.1
- chai ^4.0.0
- cheerio ^0.22.0
- classnames ^2.2.6
- connect ^3.6.6
- connect-session-sequelize ^6.0.0
- cookie ~0.4.0
- copy-webpack-plugin ^5.0.0
- cors ^2.8.4
- css-loader ^1.0.0
- device ^0.3.9
- enzyme ^3.3.0
- enzyme-adapter-react-16 ^1.1.1
- es6-promise-plugin ^4.2.2
- expect ^23.1.0
- express ^4.15.3
- express-session ^1.15.4
- express-winston ^2.5.1
- file-loader ~1.1.11
- firebase ^7.9.1
- he ^1.1.1
- html ^1.0.0
- jest ^23.5.0
- joi-browser ^13.4.0
- lodash.clonedeep ^4.5.0
- moment ^2.22.1
- nconf ^0.10.0
- node-sass ^4.9.0
- numbro ^2.1.2
- numeral ^2.0.6
- papaparse ^5.1.0
- passport ^0.4.0
- passport-google-id-token ^0.4.5
- path ^0.12.7
- pg ^7.11.0
- promise-polyfill ~8.1.0
- react ^16.4.0
- react-beautiful-dnd ^12.2.0
- react-dom ^16.4.0
- react-ga ^2.3.6
- react-hot-loader ~4.12.0
- react-hotkeys ^2.0.0
- react-joyride ^2.2.1
- react-redux ^5.0.7
- react-swipeable-views ^0.13.3
- react-transition-group ^2.5.0
- react-with-firebase-auth ^1.3.0
- redux ^4.0.0
- redux-devtools-extension ^2.13.8
- redux-mock-store ^1.5.3
- redux-thunk ^2.2.0
- reflect-metadata ^0.1.0
- request ^2.81.0
- request-promise ^4.2.2
- sass-loader ^7.0.3
- seedrandom ^3.0.5
- send ^0.16.2
- sequelize ^5.3.3
- sinon ^6.0.0
- sinon-express-mock ^2.0.0
- source-map-loader ^0.2.1
- sqlite3 ^4.0.0
- style-loader ^0.23.0
- svg-injector ^1.1.3
- ts-jest ^23.10.5
- tslint ^5.8.0
- typescript 3.7.2
- update ~0.7.4
- victory ^33.1.4
- warning ^4.0.0
- webpack ^4.12.1
- webpack-cli ^3.0.7
- webpack-dev-server ^3.1.4
- webpack-merge ^4.1.3
- whatwg-fetch ^2.0.4
- winston ^2.4.3
- yarn ^1.22.0
- actions/checkout v4 composite
- actions/setup-node v4.0.2 composite
- 1456 dependencies
- actions/cache/restore v6 composite
- actions/cache/save v6 composite
- actions/setup-node v7 composite
- actions/cache v6 composite
- actions/cache v6 composite
- 241 dependencies
- firebase-admin 14.5.0
- firebase-functions 7.4.0
Score: 5.0106352940962555