| 1 | # Build Instructions
|
|---|
| 2 |
|
|---|
| 3 | How to compile, configure, run and test the EduBerza prototype.
|
|---|
| 4 | Linked from [PrototypeImplementation](PrototypeImplementation.md).
|
|---|
| 5 |
|
|---|
| 6 | ## Development environment description
|
|---|
| 7 |
|
|---|
| 8 | | Tool | Version tested | Needed for |
|
|---|
| 9 | |-------------|-----------------------|---------------------------------------------------------------|
|
|---|
| 10 | | Go | 1.26 (1.25+ works) | Building `server/` (the CLI) and `bots/` (the market bot). |
|
|---|
| 11 | | PostgreSQL | 16 | The database. Docker image or the faculty server. |
|
|---|
| 12 | | Docker | any recent | Optional — brings up a local PostgreSQL in one command. |
|
|---|
| 13 | | `psql` | any | Optional — running the SQL scripts by hand. |
|
|---|
| 14 | | Java | 21 (8+ works) | Optional — only to open/edit the ER diagram in TerraER. |
|
|---|
| 15 | | DBeaver | any recent | Optional — only to export `relational_schema.jpg`. |
|
|---|
| 16 |
|
|---|
| 17 | Nothing else has to be installed. The only third-party Go dependency
|
|---|
| 18 | (`github.com/lib/pq`, the PostgreSQL driver) is fetched automatically by
|
|---|
| 19 | `go build` from `go.mod`/`go.sum`.
|
|---|
| 20 |
|
|---|
| 21 | ## Build instructions
|
|---|
| 22 |
|
|---|
| 23 | All commands run from the repository root.
|
|---|
| 24 |
|
|---|
| 25 | ### 1. Configure the database connection
|
|---|
| 26 |
|
|---|
| 27 | ```sh
|
|---|
| 28 | cp .env.example .env
|
|---|
| 29 | ```
|
|---|
| 30 |
|
|---|
| 31 | The defaults in `.env.example` match the bundled Docker setup. To use the
|
|---|
| 32 | faculty database instead, either edit `.env` or pass the values as real
|
|---|
| 33 | environment variables — those take precedence over the file:
|
|---|
| 34 |
|
|---|
| 35 | ```sh
|
|---|
| 36 | DBHOST=... DBPORT=5432 DBUSER=... DBPASSWORD=... DBNAME=... ./eduberza
|
|---|
| 37 | ```
|
|---|
| 38 |
|
|---|
| 39 | `.env` is deliberately not committed (see `.gitignore`) because it holds a
|
|---|
| 40 | password.
|
|---|
| 41 |
|
|---|
| 42 | ### 2. Start PostgreSQL
|
|---|
| 43 |
|
|---|
| 44 | ```sh
|
|---|
| 45 | docker compose up -d
|
|---|
| 46 | ```
|
|---|
| 47 |
|
|---|
| 48 | Skip this step if you are pointing at the faculty database.
|
|---|
| 49 |
|
|---|
| 50 | ### 3. Build
|
|---|
| 51 |
|
|---|
| 52 | ```sh
|
|---|
| 53 | go build -o eduberza ./server
|
|---|
| 54 | ```
|
|---|
| 55 |
|
|---|
| 56 | ### 4. Create the schema and load the sample data
|
|---|
| 57 |
|
|---|
| 58 | ```sh
|
|---|
| 59 | ./eduberza -init
|
|---|
| 60 | ```
|
|---|
| 61 |
|
|---|
| 62 | This runs `server/db/schema_creation.sql` and then `server/db/data_load.sql`.
|
|---|
| 63 | Both are **compiled into the binary** (`go:embed`), so `-init` works regardless
|
|---|
| 64 | of which directory you launch it from. It is destructive and idempotent — it
|
|---|
| 65 | drops and recreates the whole `project` schema, so it is also the reset button
|
|---|
| 66 | if a demo goes wrong. To reload only the data, keeping the schema:
|
|---|
| 67 |
|
|---|
| 68 | ```sh
|
|---|
| 69 | ./eduberza -load-data
|
|---|
| 70 | ```
|
|---|
| 71 |
|
|---|
| 72 | The equivalent with `psql`, if you prefer to watch the statements run:
|
|---|
| 73 |
|
|---|
| 74 | ```sh
|
|---|
| 75 | psql "postgresql://$DBUSER:$DBPASSWORD@$DBHOST:$DBPORT/$DBNAME" \
|
|---|
| 76 | -f server/db/schema_creation.sql
|
|---|
| 77 | psql "postgresql://$DBUSER:$DBPASSWORD@$DBHOST:$DBPORT/$DBNAME" \
|
|---|
| 78 | -f server/db/data_load.sql
|
|---|
| 79 | ```
|
|---|
| 80 |
|
|---|
| 81 | ### 5. Run the prototype
|
|---|
| 82 |
|
|---|
| 83 | ```sh
|
|---|
| 84 | ./eduberza
|
|---|
| 85 | ```
|
|---|
| 86 |
|
|---|
| 87 | Seed accounts — all with the password `test123`:
|
|---|
| 88 |
|
|---|
| 89 | | Username | Starting state |
|
|---|
| 90 | |-----------|-------------------------------------------------------|
|
|---|
| 91 | | `alice` | 8250.00 USD cash, holds 0.5 ETH — best demo account |
|
|---|
| 92 | | `bob` | 5000.00 USD cash, no positions |
|
|---|
| 93 | | `charlie` | 2500.00 USD cash, no positions |
|
|---|
| 94 |
|
|---|
| 95 | ### 6. Optional — run the market simulation bot
|
|---|
| 96 |
|
|---|
| 97 | In a second terminal:
|
|---|
| 98 |
|
|---|
| 99 | ```sh
|
|---|
| 100 | go run ./bots
|
|---|
| 101 | ```
|
|---|
| 102 |
|
|---|
| 103 | The bot walks the price of every active market, inserts a row into
|
|---|
| 104 | `market_trades` on each tick and upserts the current 1-minute candle. Prices in
|
|---|
| 105 | the CLI change while it runs, because the current price is always read from the
|
|---|
| 106 | most recent trade (`v_latest_prices`), never from a stored column.
|
|---|
| 107 |
|
|---|
| 108 | ## Testing instructions
|
|---|
| 109 |
|
|---|
| 110 | ### Mini-guide to the application
|
|---|
| 111 |
|
|---|
| 112 | The CLI has two menus. Before logging in: **Register**, **Login**,
|
|---|
| 113 | **Browse markets**. After logging in: **View balance**, **Deposit virtual
|
|---|
| 114 | funds**, **Browse markets**, **Place market BUY order**, **Place market SELL
|
|---|
| 115 | order**, **View portfolio**, **View transaction history**, **Manage watchlist**,
|
|---|
| 116 | **Logout**.
|
|---|
| 117 |
|
|---|
| 118 | You never have to remember an identifier. Markets are always printed as a
|
|---|
| 119 | numbered list with their current price before you are asked which one you want,
|
|---|
| 120 | and assets are referred to by symbol (`BTC`, `ETH`, …), never by database id.
|
|---|
| 121 |
|
|---|
| 122 | ### End-to-end smoke test
|
|---|
| 123 |
|
|---|
| 124 | Verified on 2026-08-07 against PostgreSQL 16 with freshly loaded sample data.
|
|---|
| 125 | Expected values are exact.
|
|---|
| 126 |
|
|---|
| 127 | 1. `./eduberza -init` — prints `Database initialised.`
|
|---|
| 128 | 2. `./eduberza`, then `[2] Login` → `alice` / `test123` → `Login successful.`
|
|---|
| 129 | 3. `[6] View portfolio` → one row: `ETH 0.5000` at avg 3500.000000, current
|
|---|
| 130 | 3520.000000, value 1760.0000, unrealised P/L `+10.0000`. Cash available
|
|---|
| 131 | 8250.0000, net worth 10010.0000.
|
|---|
| 132 | 4. `[4] Place market BUY order` → `BTC` → `0.01` →
|
|---|
| 133 | `Order executed: buy 0.0100 BTC @ 67140.000000 (notional 671.4000 USD)`.
|
|---|
| 134 | 5. `[6] View portfolio` → now BTC *and* ETH, total value 2431.4000, cash
|
|---|
| 135 | 7578.6000 (= 8250.00 − 671.40), net worth still 10010.0000.
|
|---|
| 136 | 6. `[5] Place market SELL order` → `ETH` → `0.5` →
|
|---|
| 137 | `Order executed: sell 0.5000 ETH @ 3520.000000 (notional 1760.0000 USD)`.
|
|---|
| 138 | 7. `[7] View transaction history` → deposit, buy, buy, sell, newest first.
|
|---|
| 139 | 8. `[8] Manage watchlist` → `[1] List items` → alice's `Favorites` contains
|
|---|
| 140 | BTC, ETH, SOL with live prices.
|
|---|
| 141 | 9. `[9] Logout`, then `[0] Exit`.
|
|---|
| 142 |
|
|---|
| 143 | ### Testing the failure paths
|
|---|
| 144 |
|
|---|
| 145 | These matter more than the happy path, because they are what proves the
|
|---|
| 146 | transactions actually roll back:
|
|---|
| 147 |
|
|---|
| 148 | - **Insufficient funds:** log in as `charlie` (2500 USD) and try to buy `1` BTC.
|
|---|
| 149 | Expect `Insufficient funds: need 67140.0000, have 2500.0000` and *no* change
|
|---|
| 150 | to any table — no order row, no ledger entry, no holding.
|
|---|
| 151 | - **Insufficient holding:** as `bob` (no positions), try to sell `1` ETH.
|
|---|
| 152 | Expect `Insufficient holding: trying to sell 1.0000, hold 0.0000`.
|
|---|
| 153 | - **Duplicate registration:** register with username `alice`. Expect
|
|---|
| 154 | `Username or email already taken.`
|
|---|
| 155 | - **Wrong password:** log in as `alice` with any wrong password. Expect
|
|---|
| 156 | `Invalid credentials.` — and note the same message for an unknown username, so
|
|---|
| 157 | the prototype does not leak which accounts exist.
|
|---|
| 158 |
|
|---|
| 159 | ### For the public presentation
|
|---|
| 160 |
|
|---|
| 161 | Demo with `alice` (already has a position, so the portfolio screen is not
|
|---|
| 162 | empty), and register a brand-new account live to show UC0001. Run the bot in a
|
|---|
| 163 | background terminal so the prices visibly move between two portfolio refreshes.
|
|---|
| 164 |
|
|---|
| 165 | ## Editing the ER diagram
|
|---|
| 166 |
|
|---|
| 167 | TerraER is a third-party tool and is deliberately **not** committed to this
|
|---|
| 168 | repository. Download the teacher's build from
|
|---|
| 169 | <https://bazi.finki.ukim.mk/resources/Software/> and run it:
|
|---|
| 170 |
|
|---|
| 171 | ```sh
|
|---|
| 172 | java -jar TerraER3.11.jar # then File → Open → docs/ERModel_v01.xml
|
|---|
| 173 | ```
|
|---|
| 174 |
|
|---|
| 175 | Save new versions as `ERModel_v02.xml`, `ERModel_v03.xml`, … and export a
|
|---|
| 176 | matching PNG for each. TerraER does not add the extension itself — type
|
|---|
| 177 | `.xml` explicitly or the file will not reopen.
|
|---|
| 178 |
|
|---|
| 179 | ## Up-to-date source code
|
|---|
| 180 |
|
|---|
| 181 | The repository is pushed to the FINKI DEVELOP git server; see the Repositories
|
|---|
| 182 | section in EPRMS for the clone URL and credentials.
|
|---|
| 183 |
|
|---|
| 184 | ### About the source code
|
|---|
| 185 |
|
|---|
| 186 | - All source needed to run the prototype is in this repository: the CLI
|
|---|
| 187 | (`server/`), the market bot (`bots/`), the DDL script and the sample-data
|
|---|
| 188 | script (`server/db/`).
|
|---|
| 189 | - Third-party Go libraries are **not** vendored — `go build` downloads
|
|---|
| 190 | `github.com/lib/pq` using the pinned versions in `go.mod` and `go.sum`.
|
|---|
| 191 | - Third-party executables are **not** committed. `.gitignore` excludes `*.jar`;
|
|---|
| 192 | TerraER is downloaded from the URL above.
|
|---|
| 193 | - No third-party images, styles or frameworks are used, and there are no
|
|---|
| 194 | images in the prototype at all — the interface is text.
|
|---|