Ignore:
Timestamp:
09/24/26 17:43:19 (5 days ago)
Author:
Stefan <trsunovstefan@…>
Branches:
main
Children:
0cee8ec
Parents:
a531b45
Message:

Wiki docs, phase 6 and phase 7 added

File:
1 edited

Legend:

Unmodified
Added
Removed
  • docs/P4-Prototype/BuildInstructions.md

    ra531b45 ref1c1c7  
    11# Build Instructions
    22
    3 How to compile, configure, run and test the EduBerza prototype.
    4 Linked from [PrototypeImplementation](PrototypeImplementation.md).
     3This page explains how to compile, configure, run and test the EduBerza prototype.
     4It is linked from [PrototypeImplementation](PrototypeImplementation.md).
    55
    66## Development environment description
    … …  
    88| Tool        | Version tested        | Needed for                                                    |
    99|-------------|-----------------------|---------------------------------------------------------------|
    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`.
     10| Go          | 1.26.0 (`go.mod` asks for 1.25 or newer) | Building `server/` (the CLI) and `bots/` (the market bot). |
     11| PostgreSQL  | 16.3 (Docker container) | The database. Either the local Docker container or the faculty server. |
     12| Docker + Docker Compose | any recent | Optional. Starts a local PostgreSQL with one command. |
     13| `psql`      | 16                    | Optional. Only for running the SQL scripts by hand.            |
     14| Java        | 21 (8+ works)         | Optional. Only to open or edit the ER diagram in TerraER.      |
     15| DBeaver     | any recent            | Optional. Only to export `relational_schema.jpg`.              |
     16
     17About the PostgreSQL version: `docker-compose.yml` uses the image `postgres` without a version
     18tag. Docker therefore starts whatever version of the official image it has pulled. On the
     19machine where the prototype was tested, that was PostgreSQL 16.3. The only extension the schema
     20needs is `pgcrypto` (`CREATE EXTENSION IF NOT EXISTS pgcrypto`). It ships with PostgreSQL and is
     21included in the official image.
     22
     23You do not need to install anything else. The only third-party Go library is the PostgreSQL
     24driver `github.com/lib/pq`. `go build` downloads it automatically, at the version pinned in
     25`go.mod` and `go.sum`.
    2026
    2127## Build instructions
    2228
    23 All commands run from the repository root.
     29Run all commands from the repository root.
    2430
    2531### 1. Configure the database connection
    … …  
    2935```
    3036
    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:
     37The defaults in `.env.example` (`localhost:5433`, user `bp_project`, database `bp_database`)
     38match the bundled Docker setup. To use the faculty database instead, edit `.env`, or pass the
     39values as real environment variables. Real environment variables take precedence over the file:
    3440
    3541```sh
    … …  
    3743```
    3844
    39 `.env` is deliberately not committed (see `.gitignore`) because it holds a
    40 password.
     45`.env` is not committed on purpose (see `.gitignore`), because it holds a password.
    4146
    4247### 2. Start PostgreSQL
    … …  
    4651```
    4752
    48 Skip this step if you are pointing at the faculty database.
     53Skip this step if you use the faculty database.
    4954
    5055### 3. Build
    … …  
    6065```
    6166
    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:
     67This runs `server/db/schema_creation.sql` and then `server/db/data_load.sql`. It logs
     68`Running schema_creation.sql ...`, `Running data_load.sql ...` and `Database initialised.`,
     69then prints:
     70
     71```
     72Schema initialised. Re-run without -init to start the CLI.
     73```
     74
     75Both scripts are **compiled into the binary** (`go:embed`), so `-init` works from any
     76directory. It is destructive and can be run again any number of times: it drops and recreates
     77the whole `project` schema, so it also resets everything if a demo goes wrong. To reload only
     78the data and keep the schema:
     79
     80```sh
     81./eduberza -load-data          # prints "Sample data reloaded."
     82```
     83
     84If you prefer to watch the statements run, the same can be done with `psql`:
    7385
    7486```sh
    … …  
    8597```
    8698
    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 ### 7. Optional — richer data for the P6 reports
    109 
    110 `data_load.sql` only seeds a few minutes of trade history, which is not enough
    111 for the [top traders](../P6-AdvancedReports/AdvancedReports.md#top-traders-by-realized-performance)
    112 or [market performance](../P6-AdvancedReports/AdvancedReports.md#market-performance-leaderboard)
    113 reports (menu `[10]`/`[11]`) to show more than a single period. To see them do
    114 something more interesting, load five quarters of synthetic history on top:
     99### 6. Optional: run the market simulation bot
     100
     101In a second terminal, also from the repository root (the bot reads `.env` from the current
     102directory):
     103
     104```sh
     105go run ./bots                  # add -interval 1s for faster ticks; the default is 3s
     106```
     107
     108On every tick the bot moves the price of every active market by a small random step, inserts a
     109row into `market_trades` and updates the current 1-minute candle. Prices in the CLI change
     110while it runs, because the current price is always read from the most recent trade
     111(`v_latest_prices`) and never from a stored column. Leave the bot off if you want the exact
     112numbers in the tests below.
     113
     114### 7. Optional: richer data for the P6 reports
     115
     116`data_load.sql` seeds only a few minutes of trade history. That is not enough for the
     117[top traders](../P6-AdvancedReports/AdvancedReports.md) and
     118[market performance](../P6-AdvancedReports/AdvancedReports.md) reports (menu `[10]` and `[11]`)
     119to show more than one period. To see more interesting results, load five quarters of synthetic
     120history on top:
    115121
    116122```sh
    … …  
    119125```
    120126
    121 It is deliberately not part of `-init`/`-load-data` — see the header of
    122 [`reports_demo_data.sql`](../../server/db/reports_demo_data.sql) for why — so
    123 running it never changes the balances the smoke test below checks.
     127This script is not part of `-init` or `-load-data` on purpose. The header of
     128[`reports_demo_data.sql`](../../server/db/reports_demo_data.sql) explains why. Running it never
     129changes the balances that the tests below check.
    124130
    125131## Testing instructions
    126132
     133### How to launch and log in
     134
     135Start the prototype with `./eduberza` after steps 1–4. The sample data creates three test
     136users. All of them have the password **`test123`**:
     137
     138| Username  | Starting state after `-init` |
     139|-----------|------------------------------|
     140| `alice`   | 8250.00 USD available (1750.00 invested), holds 0.5 ETH bought at 3500.00. Watchlist "Favorites": BTC, ETH, SOL. Best demo account. |
     141| `bob`     | 5000.00 USD available, no crypto. Watchlist "Bobs Picks": BTC, DOGE. |
     142| `charlie` | 2500.00 USD available, no crypto, no watchlist yet. |
     143
     144The five sample markets are ADA, BTC, DOGE, ETH and SOL, all quoted in USD. Their starting
     145last prices are 0.45375, 67140, 0.122, 3520 and 166.1.
     146
    127147### Mini-guide to the application
    128148
    129 The CLI has two menus. Before logging in: **Register**, **Login**,
    130 **Browse markets**. After logging in: **View balance**, **Deposit virtual
    131 funds**, **Browse markets**, **Place market BUY order**, **Place market SELL
    132 order**, **View portfolio**, **View transaction history**, **Manage watchlist**,
    133 **Logout**, and two [P6](../P6-AdvancedReports/AdvancedReports.md) reports:
    134 **Report: top traders** and **Report: market performance**.
    135 
    136 You never have to remember an identifier. Markets are always printed as a
    137 numbered list with their current price before you are asked which one you want,
    138 and assets are referred to by symbol (`BTC`, `ETH`, …), never by database id.
     149You always answer with the number of a menu option. When you have to choose a market, a
     150holding or a crypto, the prototype prints a numbered list and you type the number from that
     151list. You never type an id or a symbol. A number that is not in the list is refused with
     152`Invalid choice, enter a number from 1 to N.`
     153
     154**Menu before login**
     155
     156| Option | What it does and how to use it |
     157|--------|--------------------------------|
     158| `[1] Register` | Enter a username, an e-mail (must contain `@`), your full name and a password (at least 6 characters). You get `Account created. You can now log in.`, or `Invalid email.`, `Password must be at least 6 characters.` or `Username or email already taken.` A new account starts with 0 USD. |
     159| `[2] Login` | Enter your username and password. You get `Login successful.` and the second menu. A wrong password and an unknown username both give `Invalid credentials.` |
     160| `[3] Browse markets` | Prints the numbered list of markets with their last price. |
     161| `[0] Exit` | Ends the program. |
     162
     163**Menu after login** (headed `--- Logged in as <username> ---`)
     164
     165| Option | What it does and how to use it |
     166|--------|--------------------------------|
     167| `[1] View balance` | Shows the available, invested and total USD. |
     168| `[2] Deposit virtual funds` | Enter an amount in USD. It must be a positive number, otherwise you get `Invalid amount.` You get `Deposited 500.0000 USD.` |
     169| `[3] Browse markets` | Same list as before login. |
     170| `[4] Place market BUY order` | Lists all markets, numbered, with their last price. Type the number at `Market #:`. The prototype shows the latest price. Type the quantity. You get `Order executed: buy …` or `Insufficient funds: need …, have …`. |
     171| `[5] Place market SELL order` | Lists only the cryptos you hold, numbered, with columns `Held` and `Free to sell`. Type the number at `Holding #:`, then the quantity. You get `Order executed: sell …` or `Insufficient holding: …`. If you hold nothing, you get `you hold no crypto that is free to sell`. |
     172| `[6] View portfolio` | One row per crypto you hold: quantity, reserved, available, average buy price, current price, value and unrealised P/L. Then your cash, portfolio value and net worth. |
     173| `[7] View transaction history` | Your last 20 ledger entries (deposits, buys, sells), newest first. |
     174| `[8] Manage watchlist` | Opens a submenu: `[1] List items` shows your watchlist with last prices. `[2] Add crypto` lists, numbered, the cryptos not on it yet; type a number. `[3] Remove crypto` lists, numbered, the cryptos on it; type a number. `[0] Back` returns. A user without a watchlist gets one named "Favorites" the first time. |
     175| `[9] Logout` | Back to the first menu. |
     176| `[10] Report: top traders` | P6 report. Enter a start date (inclusive) and an end date (exclusive) as `YYYY-MM-DD`. |
     177| `[11] Report: market performance` | P6 report, with the same two dates. |
     178| `[0] Exit` | Ends the program. |
    139179
    140180### End-to-end smoke test
    141181
    142 Verified on 2026-09-16 against PostgreSQL 16 with freshly loaded sample data.
    143 Expected values are exact.
    144 
    145 1. `./eduberza -init` — prints `Database initialised.`
    146 2. `./eduberza`, then `[2] Login` → `alice` / `test123` → `Login successful.`
    147 3. `[6] View portfolio` → one row: `ETH 0.5000` reserved 0.0000, available
    148    0.5000, at avg 3500.000000, current 3520.000000, value 1760.0000,
    149    unrealised P/L `+10.0000`. Cash available 8250.0000, net worth 10010.0000.
    150 4. `[4] Place market BUY order` → `BTC` → `0.01` →
     182These values were checked on 2026-09-24 against freshly loaded sample data (PostgreSQL 16.3),
     183with the bot not running. The expected values are exact.
     184
     1851. `./eduberza -init` prints `Schema initialised. Re-run without -init to start the CLI.`
     1862. `./eduberza`, then `2` (Login), then `alice` / `test123` gives `Login successful.`
     1873. `6` (View portfolio) shows one row: `ETH`, quantity 0.5000, reserved 0.0000, available
     188   0.5000, average buy 3500.000000, current 3520.000000, value 1760.0000, unrealised P/L
     189   `+10.0000`. Cash available is 8250.0000 and net worth is 10010.0000.
     1904. `4` (BUY). The market list shows `1 ADA`, `2 BTC`, `3 DOGE`, `4 ETH`, `5 SOL`. Type `2` at
     191   `Market #:`, then `0.01` at `Quantity:`. The result is
    151192   `Order executed: buy 0.0100 BTC @ 67140.000000 (notional 671.4000 USD)`.
    152 5. `[6] View portfolio` → now BTC *and* ETH, total value 2431.4000, cash
    153    7578.6000 (= 8250.00 − 671.40), net worth still 10010.0000.
    154 6. `[5] Place market SELL order` → `ETH` → `0.5` →
     1935. `6` (View portfolio) now shows BTC *and* ETH, with total value 2431.4000, cash 7578.6000
     194   (= 8250.00 − 671.40), and net worth still 10010.0000.
     1956. `5` (SELL). The holdings list shows `1 BTC` (held 0.0100) and `2 ETH` (held 0.5000). Type
     196   `2` at `Holding #:`, then `0.5`. The result is
    155197   `Order executed: sell 0.5000 ETH @ 3520.000000 (notional 1760.0000 USD)`.
    156 7. `[7] View transaction history` → deposit, buy, buy, sell, newest first.
    157 8. `[8] Manage watchlist` → `[1] List items` → alice's `Favorites` contains
    158    BTC, ETH, SOL with live prices.
    159 9. `[9] Logout`, then `[0] Exit`.
     1987. `7` (View transaction history) lists, newest first: the `sell` (+1760.0000), the `buy` of
     199   BTC (−671.4000), then the two rows from the sample data, which have the same timestamp:
     200   `deposit` 10000.0000 "Initial virtual deposit" and `buy` −1750.0000 "Market buy 0.5 ETH @
     201   3500.00".
     2028. `8` (Manage watchlist), then `1` (List items), shows alice's watchlist with BTC, ETH and SOL
     203   and their last prices. Then `2` (Add crypto) lists `1 ADA` and `2 DOGE`; type `1` and you get
     204   `Added ADA.` Then `0` (Back).
     2059. `9` (Logout), then `0` (Exit).
    160206
    161207### Testing the failure paths
    162208
    163 These matter more than the happy path, because they are what proves the
    164 transactions actually roll back:
    165 
    166 - **Insufficient funds:** log in as `charlie` (2500 USD) and try to buy `1` BTC.
    167   Expect `Insufficient funds: need 67140.0000, have 2500.0000` and *no* change
    168   to any table — no order row, no ledger entry, no holding.
    169 - **Insufficient holding:** as `bob` (no positions), try to sell `1` ETH.
    170   Expect `Insufficient holding: trying to sell 1.0000, available 0.0000 (of
    171   0.0000 held, 0.0000 reserved)`.
    172 - **Two sell orders racing for the same crypto:** give `alice` a 2 BTC holding
    173   and start two `eduberza` processes at once, each selling `1.5` BTC (together
    174   3 BTC, more than she has). Expect exactly one `Order executed`, and the
    175   other `Insufficient holding` reading the post-commit quantity — see
    176   [UseCase0005Implementation](UseCase0005Implementation.md) for the exact
    177   transcript. This is the concurrency guarantee that
    178   `holdings.reserved_quantity` and the `SELECT ... FOR UPDATE` lock together
    179   provide.
     209These matter more than the happy path, because they prove that the transactions really roll
     210back and that invalid choices are refused:
     211
     212- **Insufficient funds:** log in as `charlie` (2500 USD). Choose `4`, market `2` (BTC),
     213  quantity `1`. Expect `Insufficient funds: need 67140.0000, have 2500.0000` and *no* change to
     214  any table: no order row, no ledger entry, no holding.
     215- **Insufficient holding:** on fresh data (`./eduberza -load-data`), log in as `alice`. Choose
     216  `5`; the list shows only `1 ETH` (held 0.5000, free 0.5000). Choose `1`, quantity `5`. Expect
     217  `Insufficient holding: trying to sell 5.0000, available 0.5000 (of 0.5000 held, 0.0000 reserved)`.
     218- **Nothing to sell:** as `bob` (no crypto), choose `5`. The holdings list is empty, and you
     219  get `you hold no crypto that is free to sell` without being asked for a number.
     220- **Invalid choice from a list:** in any list (for example `8`, then `3` Remove crypto), type a
     221  number larger than the list. Expect `Invalid choice, enter a number from 1 to N.`
     222- **Invalid deposit:** choose `2` and enter `-50`. Expect `Invalid amount.`
    180223- **Duplicate registration:** register with username `alice`. Expect
    181224  `Username or email already taken.`
     225- **Invalid e-mail:** register with an e-mail without `@`. Expect `Invalid email.`
    182226- **Wrong password:** log in as `alice` with any wrong password. Expect
    183   `Invalid credentials.` — and note the same message for an unknown username, so
    184   the prototype does not leak which accounts exist.
     227  `Invalid credentials.` An unknown username gives the same message, so the prototype does not
     228  reveal which accounts exist.
     229
     230The concurrency guarantee of the sell path (two processes selling the same crypto at the same
     231moment) cannot be reproduced by typing into two terminals, because each order commits within
     232milliseconds. It is described in [UseCase0005Implementation](UseCase0005Implementation.md).
    185233
    186234### For the public presentation
    187235
    188 Demo with `alice` (already has a position, so the portfolio screen is not
    189 empty), and register a brand-new account live to show UC0001. Run the bot in a
    190 background terminal so the prices visibly move between two portfolio refreshes.
     236Demo with `alice`. She already has a position, so the portfolio screen is not empty. Register a
     237brand-new account live to show UC0001. Run the bot in a background terminal so the prices
     238visibly move between two portfolio refreshes.
    191239
    192240## Editing the ER diagram
    193241
    194 TerraER is a third-party tool and is deliberately **not** committed to this
    195 repository. Download the teacher's build from
    196 <https://bazi.finki.ukim.mk/resources/Software/> and run it:
    197 
    198 ```sh
    199 java -jar TerraER3.11.jar     # then File → Open → docs/ERModel_v01.xml
    200 ```
    201 
    202 Save new versions as `ERModel_v02.xml`, `ERModel_v03.xml`, … and export a
    203 matching PNG for each. TerraER does not add the extension itself — type
    204 `.xml` explicitly or the file will not reopen.
     242TerraER is a third-party tool and is **not** committed to this repository on purpose. Download
     243the teacher's build from <https://bazi.finki.ukim.mk/resources/Software/> and run it:
     244
     245```sh
     246java -jar TerraER3.11.jar     # then File → Open → docs/P1-ConceptualModel/ERModel_v03.xml
     247```
     248
     249The current version is `ERModel_v03.xml`. Save new versions as `ERModel_v04.xml` and so on,
     250and export a matching PNG for each. TerraER does not add the extension itself: type `.xml`
     251yourself, or the file will not reopen.
    205252
    206253## Up-to-date source code
    207254
    208 The repository is pushed to the FINKI DEVELOP git server; see the Repositories
    209 section in EPRMS for the clone URL and credentials.
     255The repository is pushed to the FINKI DEVELOP git server. The clone URL and credentials are in
     256the Repositories section in EPRMS.
    210257
    211258### About the source code
    212259
    213 - All source needed to run the prototype is in this repository: the CLI
    214   (`server/`), the market bot (`bots/`), the DDL script and the sample-data
    215   script (`server/db/`).
    216 - Third-party Go libraries are **not** vendored — `go build` downloads
    217   `github.com/lib/pq` using the pinned versions in `go.mod` and `go.sum`.
    218 - Third-party executables are **not** committed. `.gitignore` excludes `*.jar`;
    219   TerraER is downloaded from the URL above.
    220 - No third-party images, styles or frameworks are used, and there are no
    221   images in the prototype at all — the interface is text.
     260- All the source needed to run the prototype is in this repository: the CLI (`server/`), the
     261  market bot (`bots/`), the DDL script and the sample-data script (`server/db/`).
     262- Third-party Go libraries are **not** vendored. `go build` downloads `github.com/lib/pq` at
     263  the versions pinned in `go.mod` and `go.sum`.
     264- Third-party executables are **not** committed. `.gitignore` excludes `*.jar`, and TerraER is
     265  downloaded from the URL above.
     266- No third-party images, styles or frameworks are used. The prototype has no images at all;
     267  the interface is text.
Note: See TracChangeset for help on using the changeset viewer.