⇧
◆ Runtime Crew · Group 02 · CSE · BRUR

Smart API Rate-Limit &
Abuse Simulator

A complete, in-memory JavaFX desktop simulator that models how cloud gateways, fintech systems and large-scale web services meter API traffic, enforce rate-limit policies, detect abusive behaviour and generate security reports — zero network, zero server, 100% OOP. This page is the full A→Z documentation, architecture graph and presentation deck for the entire codebase.

Java 17+ JavaFX 21.0.2 Maven 3.8+ JUnit 5.10.2 Patterns Strategy · SoC · SRP Version 1.0 License Academic
0
Main Classes
0
Test Classes
0
Lines of Java
0
Rate Policies
0
Packages
0
Ingestion Modes
▣

Documentation Map — Read or Present in Any Order

18 chapters — 12 core + 6 reference. Click any card to jump — or press ▶ Presentation for a 14-slide deck (arrow keys / Esc).

01

Project Overview — What & Why

The problem being simulated, the solution built, and the exact boundary of scope.

In high-throughput distributed systems thousands of clients hit the same endpoints concurrently. Without control you get resource exhaustion, DoS, credential stuffing, bot scraping and unfair usage. Production gateways (Kong, AWS API Gateway, NGINX, Cloudflare) solve this with metering + policy + anomaly engines.

This project rebuilds that internal logical behaviour as a desktop app: every request is an object, every rule is a policy object, every verdict is a report — all executed in memory with the Java Time API and collections.

Mandatory features delivered: register API clients → record simulated requests → apply rate-limit policies → detect excessive requests inside time windows → generate a per-client abuse report.

✗  NOT Simulated

Real NetworkingHTTP / REST SocketsReal Servers Live DatabasesLogin / Payments
⇣ logical behaviour only

✓  IS Simulated

Request lifecycleRate-limit metering Abuse / anomaly detectionQuota & block cooldown Violation escalationAudit & usage reports
Request log + rule engine — built purely from Java objects & collections

🎯Core Objective

Track client request activity → apply rate-limiting rules → detect abnormal/abusive patterns → generate a per-client usage & violation report.

🧠Core OOP Concepts

Domain modelling, encapsulation of counters/thresholds, polymorphic policy evaluation, Strategy-like design, type-safe Enums.

⚡Zero Overhead

No sockets, no latency, no external infra. 100% in-memory with Map/List, LocalDateTime and Duration.

📊Visual Analytics

Reactive dark-mode JavaFX dashboard: metric cards, live line chart, bar chart, sortable activity table, console log, report dialogs.

🔌Pluggable Engine

5 interchangeable RatePolicy implementations hot-swapped at runtime through one unified evaluate() contract.

🗃Persistent CSV

Clients, services and full request logs survive restarts through data/*.csv with automatic reload on boot.

02

Technology Stack & Project Facts

Everything required to build, run and test the simulator.

ComponentVersionRole in project
JDK17 / 21Language runtime, streams, Java Time API
JavaFX Controls21.0.2Dashboard, tables, charts, dialogs
JavaFX FXML21.0.2Declared dependency for view composition
Maven3.8+Build, dependency & javafx-maven-plugin
JUnit Jupiter5.10.2Unit tests for loader / generator / report / chart
mainClasscom.smartratelimit_abuse.MainAppJavaFX Application entry point
GroupIdcom.runtime_crewArtifact api-ratelimit-simulator:1.0
Compilerrelease 17 · -Xlint:allWarnings enabled for clean code
Scene size1000 × 620Stage set in MainApp.start()
$mvn clean test
$mvn javafx:run
$mvn clean package
<!-- pom.xml core coordinates -->
<groupId>com.runtime_crew</groupId>
<artifactId>api-ratelimit-simulator</artifactId>
<version>1.0</version>

<!-- javafx-maven-plugin -->
<mainClass>com.smartratelimit_abuse.MainApp</mainClass>
Domain model Policy Service UI Multi-service Test
03

Architecture — Layered Graph

Five layers — Bootstrap → Presentation → Application Service → Policy Strategy → Domain Model → Storage. Fig 3.1 shows responsibility + API of every layer, Fig 3.2 the Strategy UML, Fig 3.3 the package import graph (verified against the source), and the contract table lists what each layer may touch.

⑟ Bootstrap com.smartratelimit_abuse.MainApp 1 class start(Stage) → new EnhancedDashboardView() → scene.show()

① Presentation Layer — JavaFX

api_simulator.ui.dashboard · api_simulator.multiservice.ui 17 classes · 2,909 LOC

Owns the scene graph only: renders state, collects user input and turns clicks into commands. No rate-limit maths lives here — it delegates to services and re-renders what comes back.

key API → DashboardActionHandler.handleSendRequest/handleSimulateBurst/handleFullReport
ControlPanelView.getSelectedClient/Type/Status · LogPanel.append · StatsPanel.updateStats
MainApp↗ EnhancedDashboardView DashboardActionHandler ControlPanelView ReportViewDialog ActivityTableView SettingsView BarChartView TrafficChartView StatsPanel ReportDialogHelper LogPanel TopBarView MultiServiceDashboardView ServiceManagementDialog ServiceSelectorView MultiServiceActionHandler MultiServiceBarChartView
⇣ handleSendRequest(ServiceRequest) · trackRequest() · analyze(log)
⇧ RequestResult · AbuseReport · Platform.runLater(refresh)

② Application Service Layer

api_simulator.service · api_simulator.multiservice.service 14 classes · 1,556 LOC

The use-case core: admission control, logging, analysis, persistence and report assembly. Pure Java — zero javafx.* imports, so it is unit-testable headlessly.

key API → RateLimitEnforcer.processRequest / shouldBlock / getRemainingQuota
RateLimitAnalyzer.analyze · RequestLogger.logRequest · ClientActivityTracker.trackRequest
EnhancedReportGenerator.generateViolationReport · DatasetLoader.loadFromFile · CsvFileHandler.appendLine
RateLimitEnforcer RateLimitAnalyzer ClientActivityTracker EnhancedReportGenerator RequestLogService ClientRegistryService DatasetLoader CsvParser CsvFileHandler RequestLogger CsvRequestLogEntry BurstTrafficGenerator MultiServiceSimulator ServiceRegistry
⇣ policy.evaluate(requestLog, report)  ×  5 policies in one loop
⇧ mutates AbuseReport (addViolation + monotonic setLevel)

③ Policy Strategy Engine — «interface» RatePolicy

api_simulator.policy 6 classes · 353 LOC

Pure functions over a time window: no I/O, no JavaFX, no globals. Each algorithm is a separate class, so adding a policy = adding one file and one List.of() entry.

key API → RatePolicy.evaluate(RequestLog, AbuseReport)
+ getName / getDescription · default evaluate(Client, ...)
RatePolicy «interface» FixedWindowPolicy SlidingWindowPolicy BurstDetectionPolicy AbnormalPatternPolicy RetryAbusePolicy
⇣ reads ServiceRequest / RequestLog
⇧ writes AbuseReport.violations + ViolationLevel

④ Domain Model Layer

api_simulator.model · api_simulator.multiservice.model 8 classes · 321 LOC

Entities and enums that carry the invariants (isMoreSevereThan, risk score, unmodifiable views). Imports nothing but the JDK — it is the innermost circle.

key API → RequestLog.addRequest · AbuseReport.setLevel/getRiskScore
ServiceRequest.getFormattedTime · ViolationLevel.isMoreSevereThan
Client ServiceRequest RequestLog AbuseReport RequestType ViolationLevel EventType ApiService
⇣ CsvFileHandler.appendLine() / readLines() / rewriteFile()
⇧ CsvParser.parseLine() → ServiceRequest (round-trip safe)

⑤ Storage — CSV files

./data · ./sample_data (project root) 2 dirs · 6 files

Human-readable text, one request per line, 18 columns. Survives restart: the dashboard reloads them at boot, so the window state can be rebuilt.

round-trip → write: buildCsvLine/escape · read: parseLine/mapMethod/mapEndpoint
data/requests.csv data/multi_requests.csv data/clients.csv data/api_services.csv sample_data/sample_requests.csv sample_data/test_requests.txt
Fig 3.1 — Layered dependency flow: ⇣ synchronous call going down · ⇧ value / callback coming back up. Each layer talks only to the layer directly below it (see the verified import graph in Fig 3.3).

Fig 3.3 — Package Import Graph (every edge below was verified against the source)

Solid blue = normal dependency · pink = multi-service module · purple dashed = composition-root wiring only · red = forbidden by the dependency rule.

com.smartratelimit_abuse MainApp · 1 class ui.dashboard 12 classes · 2,226 LOC EnhancedDashboardView · ActionHandler multiservice.ui 5 classes · 683 LOC MultiServiceDashboardView · Dialogs service 12 classes · 1,290 LOC RateLimitEnforcer · Analyzer · Reports policy 6 classes · 353 LOC «interface» RatePolicy + 5 strategies multiservice.service 2 classes · 266 LOC MultiServiceSimulator · Registry model 7 classes · 262 LOC Client · ServiceRequest · RequestLog · AbuseReport · 3 enums multiservice.model 1 class ApiService start(Stage) same layer · shares LogPanel + dialog helpers processRequest() · analyze() reads entities composition root wires the 5 policies sendRequest() RateLimitEnforcer · ClientActivityTracker evaluate() ✗ never ✗ NEVER: service → ui · policy → service · model → anything · ui → policy (except the two composition roots) · any layer skipping the one below
Fig 3.3 — 11 real import edges, 0 cycles. model imports only the JDK, policy imports only model, service imports policy + model, and no service or policy class ever imports javafx.*.
LayerPackage(s)Classes / LOCSingle responsibilityMay depend onNever touches
⑟ Bootstrapcom.smartratelimit_abuse1 / 21 JavaFX entry point: builds the dashboard, starts the primary stage ui.dashboardservice, policy, file formats
① Presentationui.dashboard
multiservice.ui
17 / 2,909 Render state, capture input, translate clicks into commands, show reports service, multiservice.*, model, policy (2 roots only)CSV parsing, rate maths
② Application Serviceservice
multiservice.service
14 / 1,556 Use cases: admission, logging, tracking, analysis, persistence, reports policy, model, java.iojavafx.* (0 imports verified)
③ Policy Strategypolicy6 / 353 Pure window algorithms: fixed, sliding, burst, anomaly, retry model, java.timeservice, ui, java.io (0 imports verified)
④ Domain Modelmodel
multiservice.model
8 / 321 Entities, enums and invariants (monotonic severity, risk score) JDK onlyany project package (0 imports verified)
⑤ Storage./data, ./sample_data2 dirs / 6 files Durable 18-column CSV logs, reloaded at boot to rebuild state written + read via servicedirect access from UI classes
Rule of thumb: dependencies always point inward/downward; the only upward flow is JavaFX callbacks (setOnAction, Platform.runLater) which carry data, not types.

Fig 3.2 — Strategy Pattern Class Graph (UML)

«interface» RatePolicy + evaluate(RequestLog, AbuseReport) + getName() / getDescription() + default evaluate(Client, ...) RateLimitAnalyzer holds List<RatePolicy> «uses» FixedWindow WARNING SlidingWindow CRITICAL BurstDetect WARN→CRIT AbnormalPattern 3 heuristics RetryAbuse WARN/CRIT implements ▷
One interface, five interchangeable algorithms — hot-swappable at runtime

🧹Strategy Pattern

RatePolicy decouples algorithms from the analyzer; no if/else chains, only polymorphic evaluate().

📦Encapsulation

Domain state private; getters return Collections.unmodifiableList/Map — external mutation impossible.

🔀Polymorphism

Heterogeneous policies run through one contract inside RateLimitAnalyzer.analyze().

🏷Rich Enums

RequestType, ViolationLevel, EventType each carry display names + descriptions.

🧱Separation of Concerns

JavaFX ≠ business logic ≠ algorithms ≠ models — each isolated in its own package.

📈Monotonic Escalation

AbuseReport.setLevel() never downgrades: NORMAL→WARNING→CRITICAL is a one-way ladder.

🔧Composition Root

Only EnhancedDashboardView (live) and MultiServiceDashboardView (built, never instantiated) construct the 5 policies and inject them into RateLimitAnalyzer — swapping an algorithm is a one-line change.

🛡Verified Dependency Rule

Import scan of all 46 files: 0 edges from model → project, 0 policy → service, 0 service → ui, and exactly 1 ui → policy (the composition root).

04

Workflow — How the Project Runs, Step by Step

Eight sub-sections: boot stack → 10-stage request graph → admission decision tree → quota lifecycle → 4 ingestion modes → one-click call chain → multi-service fan-out → runtime reconfiguration.

4.1  Application Boot Sequence

Maven launches JVM

mvn javafx:run (openjfx plugin) starts com.smartratelimit_abuse.MainApp.

MainApp.main() → launch(args)
JavaFX calls start()

start(Stage) news up the root EnhancedDashboardView, then wraps it in Scene(1000×620) + /styles/main.css.

MainApp.start()
Rate-limit core built

Enforcer 10 req / 3s window / 3s block + Analyzer with 5 policies (thresholds 5, 5, 4, 3, 8).

EnhancedDashboardView ctor
Handlers & charts wired

DashboardActionHandler, TrafficChartView, MultiServiceSimulator, ServiceSelectorView constructed and injected.

ctor lines 61–66
1-second timer starts

Timeline(KeyFrame 1s → refreshClientViews()), cycle INDEFINITE, play() — drives quota, risk badge and block countdown.

statusTimer
Layout + events + CSV

initLayout() (BorderPane), setupEvents() (all setOnAction), then loadFromCsv() restores clients, services and request history.

ctor lines 72–74
Stage shown

Title set, scene attached, stage.show(); three start-up lines are appended to the console log.

MainApp.start() → show()

Boot call-stack

mvn javafx:run
└─ com.smartratelimit_abuse.MainApp.main()
   └─ launch(args)                        // starts JavaFX Application Thread
      └─ start(Stage stage)
         ├─ new EnhancedDashboardView()
         │   ├─ enforcer  = RateLimitEnforcer(10, 3s, 3s, logger)
         │   ├─ analyzer  = RateLimitAnalyzer(5 policies)
         │   ├─ actionHandler / trafficChart / multiSimulator
         │   ├─ statusTimer = Timeline(1s → refreshClientViews)
         │   ├─ initLayout()  &  setupEvents()
         │   └─ loadFromCsv()  // clients, services, requests
         ├─ new Scene(root, 1000, 620) + /styles/main.css
         └─ stage.show()

🕑Threading model

Everything — ingestion, policy evaluation, CSV write, UI refresh — runs on the single JavaFX Application Thread. No worker threads: a burst of 20 requests is processed synchronously inside one button click.

🔄Idle loop

While idle, only statusTimer fires every second: recompute remaining quota, getTimeUntilReset(), risk badge and block countdown, then repaint.

💾State on restart

loadFromCsv() replays data/requests.csv through restoreFromLogEntries(), so the table, charts and tracker are repopulated before the window is shown.

4.2  Request Lifecycle — Main Execution Graph (stages 1–10)

MODE A · Manual ComboBox → Send Request MODE B · Burst 20 req / 10 s synthetic MODE C · Dataset CSV / TXT file import MODE D · Multi-Service N services × 1 request ServiceRequest clientId · service requestType · timestamp new ServiceRequest(...) at now() RateLimitEnforcer window 3s · max 10 req block cooldown 3s processRequest() → RequestResult recentCount < max ? YES ✓ ALLOWED write to RequestLogger quota– · status OK NO ⚠ BLOCKED blockStart = now skips RequestLogger ClientActivityTracker trackRequest(req, blocked) · success rate RateLimitAnalyzer slice last 10s → 5 policies AbuseReport: level + riskScore analyzer.analyze(log) determineEventType() + persistToCsv() ALLOWED · RATE_LIMITED · ABUSE_DETECTED data/requests.csv · LogPanel · ActivityTableView · TrafficChartView · StatsPanel · Report dialogs 1 2 3 4 5 6 7 8 9 10
Fig 4.1 — Ten stages: 1 ingest → 2 build request → 3 enforce → 4 decide → 5 allow / 6 block → 7 track → 8 analyze → 9 classify + persist → 10 render. All of it happens synchronously inside one button click.

4.3  Admission Control Decision Tree

Incoming Request READ / WRITE / UPDATE / DELETE 1 · Inside block cooldown? blockStart + 3s > now() NO 2 · recentCount ≥ max (10) ? count where |r.ts − req.ts| ≤ 3s YES YES NO ⚠ BLOCKED blockStart = now() quota pinned to 0 RequestLogger untouched ✓ ALLOWED requestLogger.logRequest() quota = 10 − recentCount returns RequestResult Cooldown expiry → automatic reset getRemainingQuota() clears the client log → full 10/10 again getTimeUntilReset() shows the countdown used by the 1s timer
Fig 4.2 — RateLimitEnforcer.shouldBlock() / processRequest() / getRemainingQuota() (lines 31–106)
ALLOWED path BLOCKED path Decision point Auto-reset

4.4  Quota Lifecycle — 10 req / 3s window / 3s block

0.0s
OK
10/10
1.0s
OK
7/10
2.0s
OK
4/10
3.0s
OK
1/10
3.4s
BLOCK
0/10 · t0
4–6s
BLOCK
0/10 cooling
6.4s
RESET
log cleared
7.0s
OK
9/10
The window counts requests within 3s of the incoming timestamp; the 11th triggers cooldown, and expiry calls clearClient() so the quota snaps back to 10/10.

4.5  Four Ingestion Modes

🖱A — Manual interactive form

handleSendRequest(clientId, type, logPanel, onUpdated) — type is randomized when null, and ALL_CLIENTS replays the same pipeline for every registered client.

💥B — High-velocity burst

generateBurst(clientId, 20, 10s) builds evenly spaced timestamps, then feeds them through processRequest() one by one: the first ~10 pass, the rest trip the cooldown.

📁C — Dataset import

DatasetLoader.loadFromFile / loadFromText accepts comma, semicolon or space separators, skips # comments and headers, and stores bad rows in getErrors() instead of aborting.

🔗D — Multi-service fan-out

sendRequest(ids, type) issues one request per service with an isolated quota key svc_<id> and returns a LinkedHashMap in selection order.

4.6  Anatomy of One Click — Exact Call Chain

// click "Send Request"  →  DashboardActionHandler.handleSendRequest(...)   (lines 62–105)
ServiceRequest req   = new ServiceRequest(clientId, type, LocalDateTime.now());  // 1 build the event
RateLimitEnforcer.RequestResult res = enforcer.processRequest(req);            // 2 shouldBlock + maybe logRequest
activityTracker.trackRequest(req, res.isBlocked());                            // 3 totals, success rate
RequestLog      log   = logger.getLog(clientId);
AbuseReport     abuse = analyzer.analyze(log);                                  // 4 five policies → level + risk
EventType       evt   = determineEventType(res, abuse);                         // 5 ALLOWED | RATE_LIMITED | ABUSE_DETECTED
String          reason = abuse.hasViolations() ? abuse.getSummary()
                        : (res.isBlocked() ? "RATE_LIMIT_EXCEEDED" : "OK");
persistToCsv(req, res, evt, abuse.getRiskScore(), reason);                     // 6 append to data/requests.csv
onUpdated.run();                                                               // 7 table + stats + charts repaint
logPanel.appendEvent(evt, clientId, reason + " | Quota: " + res.getRemainingQuota()
                       + "/" + enforcer.getMaxRequests());                      // 8 console line
Fig 4.3 — The whole pipeline is synchronous: nothing is queued, nothing runs in the background.

4.7  Mode D — Multi-service Fan-out

One click is replayed across every selected service and every resolved client. Quotas stay isolated per service because each service is addressed under its own svc_<id> key, while activity stats and CSV rows keep the real client id — two identities for one request, written to a second log file, data/multi_requests.csv.

EnhancedDashboardView :136 / :143 → if (isMultiServiceMode()) gate = serviceSelectorBox.isVisible() (:108 hidden by default) · Send → handleMultiServiceSendRequest · Burst → handleMultiServiceBurst resolveClientsForRequest(clientId) :429–440 null / blank → "WebApp" · else → that one client id ALL_CLIENTS → clientRegistry.loadAll() ?: [SuspiciousBot, WebApp, PartnerAPI] for (String client : clients) // outer loop :455 multiSimulator.sendRequest(client, selected, type) :459 · returns LinkedHashMap in selection order "%s [%s] %s -> %s | %s | Quota: %d/%d" :468 · icon, time, client, service, type, quota, risk, reason allowed++ / blocked++ → summary line :474–482 → refreshClientViews() repaints the dashboard svc_Facebook 7/10 ALLOWED key = "svc_" + serviceId (:31) · processRequest (:50) svc_Messenger 4/10 ALLOWED own counter, shared enforcer svc_Instagram 0/10 RATE_LIMITED cooldown 3s · neighbours unaffected registry defaults: Facebook · Messenger · Telegram · Instagram (ServiceRegistry:24–33) data/multi_requests.csv multiRequestLogService (:31–32) · append(...) :62–66 · same 18-column header logPanel + refreshClientViews() console :468–480 · repaint :482 · 1s statusTimer keeps quota bars live (:68)
Fig 4.4 — the live Mode D path: EnhancedDashboardView:442–514 → MultiServiceSimulator.sendRequest() (:38–71). One action, N independent counters, one CSV.

🔒Quota isolation

One shared RateLimitEnforcer, N counters: every service is addressed as svc_<id>, so 10 requests to Facebook never spend Messenger’s budget. getRemainingQuota("svc_" + svc) feeds the per-service countdown at :611.

👤Two identities per request

Enforce + analyze under svc_<id>; track + log under actualClient (:39 — blank or svc_-prefixed ids collapse back to WebApp). CSV rows therefore show client and service side by side, and ActivityTableView strips the svc_ prefix when grouping.

⚡Burst mode

handleMultiServiceBurst() :485 → simulateBurst(client, selected, burstCount=20, 10s) lays down a synthetic burst per service and replays it through the same enforcer, returning BurstResult{total, allowed, blocked} (:152) plus a rolled-up total at :509–511.

⚠Not on the live path

MultiServiceDashboardView and MultiServiceActionHandler are complete but never instantiated — MainApp opens only EnhancedDashboardView. Their private enforcer (10 / 10s / 3s, MultiServiceDashboardView:40) therefore never runs.

Actual console output

✉️ [WebApp] Sending READ request to 3 service(s)...      // :457
✅ [14:02:11] WebApp -> Facebook  | ✅ Allowed        | Quota: 7/10 | Risk: 0  | OK
⛔ [14:02:11] WebApp -> Messenger  | ⏳ Rate Limited   | Quota: 0/10 | Risk: 0  | RATE_LIMIT_EXCEEDED
⛔ [14:02:11] WebApp -> Instagram  | ⚠️ Abuse Detected | Quota: 2/10 | Risk: 55 | Burst detected: 5 requests within 3 seconds starting at 14:02:08
✅ [WebApp] Sent! Allowed: 1 | Blocked: 2                      // :480
Fig 4.5 — the exact format string from :468; risk 0 means no policy fired, 55 = 1 violation ×15 + CRITICAL bonus.

Event-type truth table

blockedhasViolations()EventTypemeaning
nono✅ ALLOWEDquota left, no policy fired
yesno⏳ RATE_LIMITED3s cooldown active on that svc_<id>
noyes⚠ ABUSE_DETECTEDpolicy hit while quota still left
yesyes⚠ ABUSE_DETECTEDboth — abuse always outranks the enforcer
Fig 4.6 — MultiServiceSimulator.determineEventType() :112–117; byte-for-byte the same logic as DashboardActionHandler:338–343 used by Modes A–C.

4.8  Runtime Reconfiguration (Settings)

⚙1 · Open the dialog

SettingsView.show() opens a 400×380 scene with max requests, window, block duration, burst count and burst duration; setOnSave(() -> applySettings(...)) binds the button.

🔄2 · Rebuild the core

applySettings() :516–540 constructs a new RateLimitEnforcer and a new RateLimitAnalyzer (Fixed & Sliding re-thresholded from the dialog), then pushes them with updateEnforcer() / updateAnalyzer() / updateBurstConfig() :532–534.

✅3 · Confirm + refresh

Success toast, a log line Settings saved: Max=%d, Window=%ds, Block=%ds, Burst=%d/%ds (EnhancedDashboardView:538), refreshClientViews(), and the dialog auto-closes after a 1-second Timeline.

⚠Known quirk — Mode D never sees it

multiSimulator was built at :65 holding the boot enforcer and analyzer. applySettings() only reassigns the view’s fields, so Mode D keeps enforcing 10 requests / 3s window / 3s block with the boot thresholds until the app is restarted.

05

Rate-Limit & Abuse Policies (Strategy Engine)

Five algorithms behind one RatePolicy interface — boot defaults taken straight from EnhancedDashboardView:54–60, the exact trigger math of every detector, and the monotonic severity ladder that feeds the risk score.

⏱ FixedWindowPolicy

→ WARNING

Counts requests falling inside a discrete window ending at the latest request timestamp.

count = |{ r : 0 ≤ latest - r.t ≤ W }|
count > max → addViolation() + setLevel(WARNING)
  • Boot default: max 5 / window 3s — strict > means it trips on the 6th request
  • Low memory, but a burst straddling two windows can slip through
policy/FixedWindowPolicy.java

🔄 SlidingWindowPolicy

→ CRITICAL

Pair scan over every continuous interval — kills boundary-burst exploits.

for start i: count = 1; for j > i: Δt = t(j) - t(i)
if Δt ≤ W: count++ → count > max → addViolation + CRITICAL
  • Boot default: max 5 / window 3s — trips on the 6th request in any window
  • Escalates straight to CRITICAL and stops scanning; the other 4 policies still run but can never lower the level
policy/SlidingWindowPolicy.java

💥 BurstDetectionPolicy

≥1 WARN ≥3 CRIT

Finds clusters of rapid-fire requests — models DoS spikes and flash mobs.

for start i: scan forward while t - t(i) ≤ 3s (breaks on first larger gap)
count ≥ 4 → burst++ + violation
bursts ≥ 3 → CRITICAL · bursts ≥ 1 → WARNING (only from NORMAL)
  • Boot default: ≥4 requests in 3 seconds (4, 3s)
  • One violation per burst start, timestamped HH:mm:ss; multiple overlapping starts multiply the count
policy/BurstDetectionPolicy.java

🧠 AbnormalPatternPolicy

WARN CRIT

Three statistical heuristics that unmask automated scripts and bots.

① hour ∈ [02:00, 05:00) & count > 3 → WARNING
② one request type > 90% of ≥10 req → scraping
③ |Δs[i] - Δs[i+1]| ≤ 1s for >70% of ≥10 req → CRITICAL bot
  • detectOffHoursActivity() · detectRequestTypeImbalance() · detectUniformIntervals()
  • Needs ≥5 requests to build the interval array; the bot verdict sets CRITICAL unconditionally (not guarded by NORMAL)
policy/AbnormalPatternPolicy.java

🔅 RetryAbusePolicy

WARN CRIT

Detects aggressive re-attempts following rejected calls.

① gaps < 1000ms counted across the log; count > 5 → CRITICAL
② longest run of gaps ≤ 2s; ≥ 8 → WARNING (only from NORMAL)
  • Boot default: (8 consecutive, 2s window)
  • detectRapidRetries() hammers sub-second · detectSuspiciousRapidRequests() resets its streak on the first slow gap
policy/RetryAbusePolicy.java

◆ RatePolicy — the Strategy contract

1 interface

One abstract method plus four defaults — every detector drops into the same slot.

abstract evaluate(RequestLog, AbuseReport)
default evaluate(Client) · evaluate(Client, RequestLog, AbuseReport)
default getName() → class simple name · getDescription()
  • policy imports model only — zero awareness of service or ui
  • Registered order: Fixed → Sliding → Burst → Abnormal → Retry
policy/RatePolicy.java · interface

🔍 RateLimitAnalyzer — the 10-second lens

5 policies

Before judging anything it trims the log to the last 10 seconds, then runs every policy over that slice.

recent = { r : now - r.t ≤ 10s }
if recent is empty → return a clean AbuseReport
else for p in policies: p.evaluate(filteredLog, report)
  • Called once per click — DashboardActionHandler:630,666 → analyze(log).getLevel()
  • addViolation() drops duplicates and blank messages, so repeated identical hits never inflate the risk score
service/RateLimitAnalyzer.java

🏁 Severity Escalation Ladder

NORMAL → WARNING → CRITICAL
setLevel(): CRITICAL is final · CRITICAL→WARNING and WARNING→NORMAL are dropped
riskScore = min(100, violations×15 + WARN 20 / CRIT 40)
  • getRiskScore() drives the dashboard risk badge · 0 when there are no violations
  • isMoreSevereThan() compares ordinal() of NORMAL / WARNING / CRITICAL
model/AbuseReport.java · model/ViolationLevel.java

5.1  Composition Root — What Is Actually Constructed

// EnhancedDashboardView:54–60  →  rebuilt identically by applySettings() at :523–530
enforcer = new RateLimitEnforcer(10, ofSeconds(3), ofSeconds(3), logger);  // 10 req · 3s window · 3s block
analyzer = new RateLimitAnalyzer(List.of(
    new FixedWindowPolicy(5, ofSeconds(3)),      // 5 / 3s   → WARNING
    new SlidingWindowPolicy(5, ofSeconds(3)),    // 5 / 3s   → CRITICAL
    new BurstDetectionPolicy(4, ofSeconds(3)),   // ≥4 / 3s  → WARNING → CRITICAL
    new AbnormalPatternPolicy(3),                // >3 night hits → WARNING
    new RetryAbusePolicy(8, ofSeconds(2))));     // 8 / 2s   → WARNING (sub-second → CRITICAL)
Only two of the five move when the user applies Settings (Fixed + Sliding inherit the new max & window); burst, pattern and retry keep their boot values forever.

5.2  Policy Decision Matrix — Which Operation Trips Which Detector

Request typeEnforcer allows whileEnforcer blocks whenDominant abuse detectorConsequence
READrequests in window < max≥ maxAbnormalPattern — type imbalance > 90%WARNING scraping / harvesting
WRITErequests in window < max≥ maxBurstDetection — ≥4 in 3sCRITICAL flash flood / DoS
UPDATErequests in window < max≥ maxRetryAbuse — ≥8 rapid consecutiveWARNING resource churn
DELETErequests in window < max≥ maxAbnormalPattern — uniform interval >70%CRITICAL bot script
ANYgap ≥ 1000ms between callsΔ < 1000ms more than 5 timesRetryAbuse — rapid retry loopCRITICAL lockout
ANYoutside 02:00–05:00>3 requests at nightAbnormalPattern — off-hoursWARNING nocturnal anomaly
Columns 2–3 are the RateLimitEnforcer (per-client quota, recentCount ≥ max → 3s block). Column 4 is never a router — all five policies always evaluate the same 10-second slice; it names the detector that produces the dominant verdict for that kind of traffic.

5.3  What Settings Can (and Cannot) Change

Setting (default)Rebuilt when appliedStays at boot value forever
Max Requests (10) · Time Window (3)Enforcer quota + FixedWindowPolicy + SlidingWindowPolicy (applySettings:523–530)—
Block Duration (3)Enforcer cooldown only—
Burst Count (20) · Burst Duration (10)Handler burst fields (DashboardActionHandler:30–31)—
——BurstDetectionPolicy(4, 3s), AbnormalPatternPolicy(3), RetryAbusePolicy(8, 2s) and the analyzer's 10 s slice — no UI control exists for any of them
Mode D never hears about Settings at all: multiSimulator is built once with the boot enforcer/analyzer (:65), so the multi-service path keeps 10 req / 3 s / 3 s no matter what the user applies.
06

Codebase Modules — Full Folder Tree (A→Z)

Every package, every file. Aggregate totals are in the strip below. The same six packages have filter buttons in section 07.

46
main classes
6,110
main lines · 5,160 SLOC
6
main packages + root
442
test lines · 4 classes
592 KB
4 runtime CSVs
940 KB
main.css + picture.png
api-ratelimit-simulator/ ├── index.html ← this documentation (single file) ├── README.md ← project readme · 11 KB ├── documentation.md ← full technical spec · 46 KB ├── details.md ← assignment brief · 5 KB ├── project_file.pdf ← assignment sheet · 185 KB ├── pom.xml ← maven build · 2 KB ├── .gitignore ← target/, .idea/, *.iml │ ├── data/ 4 CSVs · 592 KB │ ├── clients.csv clientId,name · 103 B │ ├── api_services.csv id,name,isDefault,icon,types · 42 B │ ├── requests.csv 18-column audit log · 196 KB │ └── multi_requests.csv multi-service log · 396 KB │ ├── sample_data/ │ ├── sample_requests.csv 2.5 KB seed for Import Text │ └── test_requests.txt 3.3 KB scripted sequence │ └── src/ ├── main/java/ 46 classes · 6,110 lines │ ├── com.smartratelimit_abuse/ 1 class │ │ └── MainApp.java │ └── com.runtime_crew.api_simulator/ │ ├── model/ 7 classes · 262 │ │ ├── AbuseReport.java │ │ ├── Client.java │ │ ├── EventType.java │ │ ├── RequestLog.java │ │ ├── RequestType.java │ │ ├── ServiceRequest.java │ │ └── ViolationLevel.java │ ├── policy/ 6 types · 353 │ │ ├── AbnormalPatternPolicy │ │ ├── BurstDetectionPolicy │ │ ├── FixedWindowPolicy │ │ ├── RatePolicy.java ← interface │ │ ├── RetryAbusePolicy │ │ └── SlidingWindowPolicy │ ├── service/ 12 classes · 1290 │ │ ├── BurstTrafficGenerator │ │ ├── ClientActivityTracker │ │ ├── ClientRegistryService │ │ ├── CsvFileHandler │ │ ├── CsvParser │ │ ├── CsvRequestLogEntry │ │ ├── DatasetLoader │ │ ├── EnhancedReportGenerator │ │ ├── RateLimitAnalyzer │ │ ├── RateLimitEnforcer │ │ ├── RequestLogger │ │ └── RequestLogService │ ├── ui/dashboard/ 12 classes · 2226 │ │ ├── ActivityTableView │ │ ├── BarChartView │ │ ├── ControlPanelView │ │ ├── DashboardActionHandler │ │ ├── EnhancedDashboardView │ │ ├── LogPanel │ │ ├── ReportDialogHelper │ │ ├── ReportViewDialog │ │ ├── SettingsView │ │ ├── StatsPanel │ │ ├── TopBarView │ │ └── TrafficChartView │ └── multiservice/ 8 classes · 1008 │ ├── model/ApiService │ ├── service/MultiServiceSimulator │ ├── service/ServiceRegistry │ └── ui/ (5 files) 683 │ ├── MultiServiceActionHandler │ ├── MultiServiceBarChartView │ ├── MultiServiceDashboardView │ ├── ServiceManagementDialog │ └── ServiceSelectorView │ ├── main/resources/ │ ├── styles/main.css dark theme · 10 KB │ └── picture.png app icon · 930 KB │ └── test/java/ 4 classes · 442 lines └── com.runtime_crew.api_simulator/ ├── service/BurstTrafficGeneratorTest ├── service/DatasetLoaderTest ├── service/EnhancedReportGeneratorTest └── ui/dashboard/BarChartViewTest

📁model — Domain

7 immutable value objects & enums. The shared vocabulary of the whole system: a request, a client, a log, a report, a severity.

⚙policy — Strategy

1 interface + 5 algorithms. Only this package knows how abuse is judged; nothing above knows the details.

🛠service — Business Logic

12 engines: admission control, analysis orchestration, activity statistics, CSV ingestion & persistence, ASCII/HTML report rendering.

🖥ui.dashboard — Presentation

12 files: 11 JavaFX views/helpers plus DashboardActionHandler. EnhancedDashboardView is the composition root and coordinator.

🌐multiservice — Fan-out

8 classes simulating many APIs at once: CSV-backed ServiceRegistry, MultiServiceSimulator, action handler, selector, management dialog, bar chart and dashboard.

🧩test — Verification

4 JUnit 5 classes, 442 lines (359 SLOC): BurstTrafficGeneratorTest · DatasetLoaderTest · EnhancedReportGeneratorTest · BarChartViewTest.

📄Roots & Data

Four documents (index.html, README.md, documentation.md, details.md) plus the assignment PDF and pom.xml. The four CSVs under data/ are read at boot and appended to on every click by RequestLogService.

07

Component Index — Every Class & Interface (A→Z)

Search or filter all 56 entries by name, responsibility or key API — 46 main classes (one of them the RatePolicy interface, 4 of them carrying 6 nested types) + 4 test classes, every row verified against the source.

#Class / InterfacePackageTypeResponsibilityKey API
08

Data Model & File Formats

Persistence schemas, sample datasets, domain attribute dictionary and parser rules.

FileSchemaPurpose
data/clients.csvclientId,nameRegistered API consumers; 4 defaults auto-seeded (MobileApp, WebApp, PartnerAPI, SuspiciousBot)
data/api_services.csvid,name,isDefault,icon,enabledEventTypesFacebook / Messenger / Telegram / Instagram + custom services
data/requests.csvrequestId, clientId, serviceId, endpoint, method, timestamp, status, responseCode, responseTimeMs, rateLimit, remaining, windowSeconds, abuseDetected, abuseReason, severity, eventType, riskScore, reasonSingle-service audit trail (18 columns)
data/multi_requests.csvsame 18 columns, serviceId populatedMulti-service fan-out trail
sample_data/sample_requests.csvtimestamp,clientId,requestTypeReplayable normal / abusive sessions
sample_data/test_requests.txt# comments + rowsLoader robustness test input

Domain Attribute Dictionary

AttributeTypeMeaning
timestampLocalDateTimeWhen the request happened
requestTypeRequestType enumREAD · WRITE · UPDATE · DELETE
clientIdStringWho made the request
serviceStringWhich API service was hit (multi-mode)
statusboolean / StringALLOWED vs BLOCKED
severityViolationLevelNORMAL · WARNING · CRITICAL
eventTypeEventTypeREQUEST · ALLOWED · RATE_LIMITED · ABUSE_DETECTED · BLOCKED
riskScoreint 0–100Computed abuse risk

Dataset Parsing Rules (DatasetLoader)

// accepted delimiters
,   ;   \s+            // comma | semicolon | whitespace

// skipped lines
// empty · lines starting with # or //
// header containing "timestamp" or "clientId"

// accepted timestamp formats
yyyy-MM-dd'T'HH:mm:ss   // ISO-8601
yyyy-MM-dd HH:mm:ss     // date + time
HH:mm:ss                // time only (today)
HH:mm                   // short time (today)

// fault tolerance: bad rows go to errors list
loader.getErrors();   loader.getSuccessCount();
09

UI Component Map — Dashboard Wireframe

How the 12 JavaFX views compose the runtime screen (BorderPane layout, 1000×620).

Smart API Rate-Limit & Abuse Simulator TopBarView — title · subtitle · team banner
ControlPanelView
Client ▾  ControlPanelView / ClientRegistryService
Type ▾ READ  ·  Status ▾ ALL
Service ▾ (multi-service mode)
SEND REQUEST
GENERATE BURST (20 / 10s)
LOAD DATASET (.csv / .txt)
REGISTER · RENAME · DELETE
FULL REPORT · QUICK · COMPARE
BAR CHART · EXPORT · SETTINGS
StatsPanel
320
Total
32
Allowed
288
Blocked
10%
Rate
⏱ Quota 4/10  ·  ⚠ Risk WARNING
ActivityTableView — filterable chronology
TimeClient / ServiceTypeStatus
10:00:01MobileAppREADALLOWED
10:00:04MobileAppWRITEALLOWED
10:00:07MobileAppREADBLOCKED
10:00:09WebApp · FBDELETEALLOWED
10:00:12SuspiciousBotREADBLOCKED
TrafficChartView — 60s live line chart
Allowed Blocked
LogPanel — live audit console
✓ 10:00:07 MobileApp — ALLOWED | Quota: 3/10
⚠ 10:00:12 SuspiciousBot — BLOCKED | Quota: 0/10 RATE LIMIT EXCEEDED
! 10:00:13 AbuseReport: sliding window violation · risk 55
Fig 9.1 — EnhancedDashboardView = BorderPane(top=TopBar, left=ControlPanel+Stats, center=Table+Chart, bottom=LogPanel)

🗖ReportViewDialog

Modal monospaced ASCII security audit with copy-to-clipboard and file export.

⚙SettingsView

Editable max requests · time window · block duration · burst count · burst duration with validation.

📊BarChartView

Allowed-vs-blocked per service / per type via static aggregateServiceStats().

🧮DashboardActionHandler

Command layer: 10+ handle*() methods orchestrate enforcer, tracker, logger, report and CSV.

🔀ALL_CLIENTS mode

Aggregates every tenant's records, sorts descending, enables fleet-wide comparison reports.

🔄1s status timer

Background Timeline refreshes remaining quota, risk badge and block countdown every second.

10

Reporting & Analytics Output

EnhancedReportGenerator — the largest service class, second-largest file in the repo. Six public methods, zero file I/O inside: everything returns a String built with StringBuilder.

                         API SECURITY REPORT
                   Full Violation & Usage Analysis

  Generated: 27 Sep 2026 · 22:54:06       [ CRITICAL ]

  CLIENT INFORMATION
  ------------------------------------------------------------------

  CLIENT ID           CLIENT_A
  REPORT DATE         27 Sep 2026 · 22:54:06
  SEVERITY            ● CRITICAL

  ------------------------------------------------------------------

  USAGE OVERVIEW

  TOTAL REQUESTS     80

  ALLOWED            8          10.0%

  BLOCKED            72         90.0% limit exceeded


  SUCCESS RATE

  10.0%   █░░░░░░░░░

  Last Activity: 19:15:55

  REQUEST TYPE DISTRIBUTION

  READ
  80 requests 100.0%
  ██████████

  SECURITY STATUS
  ------------------------------------------------------------------

                    1 VIOLATION(S) DETECTED

    1. Sliding window abuse detected: 6 requests within 3s window (limit: 5)

  ------------------------------------------------------------------

  RECOMMENDATION
  ------------------------------------------------------------------

  ✖  CRITICAL

  Immediate action required! Rate limit threshold breach detected.
  Consider blocking this client temporarily or rotating API credentials.
  Low success rate: Check client integration and error handling.
  ------------------------------------------------------------------
generateViolationReport() — single-client deep audit (68 columns). Snapshot above was produced by actually running the class: 8 allowed + 72 blocked requests fed in, report printed out.

Report API Surface

MethodOutput
generateViolationReport()Single-client deep audit + recommendation (:16, 68 cols)
generateUsageReport()Single-client quick summary: usage stats, types, timeline, alerts (:123)
generateAllClientsUsageReport()Fleet summary with aligned fixed-width tables + optional service breakdown (:185)
generateAllClientsFullReport()Full 70-column matrix, single & multi-service (:401)
generateComparisonReport()Full HTML document, hard-coded dark hex — dead code, never called (:275)
buildServiceComparison()Returns a Map keyed by service (TreeMap), feeds the UI table — no text output (:383)
getProgressBar(n)private helper: █×filled + ░×empty (:352)

Severity → Recommendation Mapping

LevelExact advice printed
NORMAL“Usage is within normal operational thresholds. No immediate action is required.”
WARNING“High traffic frequency detected. Monitor client activity. Review request patterns for potential abuse.”
CRITICAL“Immediate action required! Rate limit threshold breach detected. Consider blocking this client temporarily or rotating API credentials.” — plus a low-success-rate line when the rate drops under 50%.

How reports reach the user

Single caller

The only production caller is DashboardActionHandler (7 call sites: :203, 210, 227, 233, 241, 259, 273). ReportViewDialog only renders a String it is handed — it never calls the generator.

Export is user-driven

Nothing is written automatically and no report/ directory exists. Export happens through a FileChooser (ReportViewDialog:265–279, DashboardActionHandler:260–278) with default names report_*.txt, <client>_report_*.txt, ALL_CLIENTS_report_*.txt.

Icons

Severity dot is always \u25CF (●); the icon is ✖ CRITICAL / ⚠ WARNING / ✔ otherwise. Bars are █ filled + ░ empty, width 10 by default.

11

Automated Test Suite

JUnit Jupiter 5.10.2 (test scope, pom.xml:28–33) · mvn test · 4 classes, 15 tests, 442 lines (359 SLOC) — all green in ~9 s.

Test Class@TestTargetWhat it actually assertsFocus areas
BurstTrafficGeneratorTest1BurstTrafficGeneratorgenerateBurst("CLIENT_A", 20, 10s) returns exactly 20 requests, all stamped CLIENT_A with non-null type & timestamp, and timestamps never run backwardshigh-volume synthesis
DatasetLoaderTest3DatasetLoaderComma-delimited line parses to hour/minute/second + client + type · comment & header lines are skipped (3 ok, 0 errors) · sample_data/test_requests.txt and sample_requests.csv exist and load (run from the Maven basedir)parsing, fixtures
EnhancedReportGeneratorTest6EnhancedReportGeneratorFull-report section headers · per-service grouping (Facebook 2/1/1 @ 50.0%, Instagram last activity 22:45:09) · blank / "-" services and null input yield empty maps · fixed-width CLIENT/SERVICE tables stay column-aligned, incl. an over-long client name, with 58.6% / 65.5% rate cellsformatting integrity
BarChartViewTest5BarChartViewStatic aggregateServiceStats(): per-service allowed/blocked pairs, null/blank/"-" services excluded and trimmed, counters accumulate across calls, null args are safe no-ops · plus an integration run through MultiServiceSimulator + enforcer + analyzer into a temp CSVnull-safety, aggregation
Honest coverage

4 of 46 production classes get direct assertions (8.7%). Zero @BeforeEach, zero assertThrows. Semicolon/space delimiters, malformed-line tolerance and ASCII progress bars exist in production but have no assertions — the table above states only what is proven.

Not covered at all

All 5 policy internals beyond construction, the JavaFX dashboard views, the multiservice UI, ClientRegistryService, the CSV parser/handler and MainApp — 33 of 46 classes are exercised only by running the app itself.

$mvn clean test
[INFO] Running com.runtime_crew.api_simulator.service.BurstTrafficGeneratorTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] Running com.runtime_crew.api_simulator.service.DatasetLoaderTest
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] Running com.runtime_crew.api_simulator.service.EnhancedReportGeneratorTest
[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0
[INFO] Running com.runtime_crew.api_simulator.ui.dashboard.BarChartViewTest
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO] Results: Tests run: 15, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS — Total time: 8.976 s (verified 2026-09-27)
12

Setup, Build & Run Guide

From clone to running app in five commands. Coordinates com.runtime_crew:api-ratelimit-simulator:1.0 — Maven-only (no mvnw, no shell/batch scripts, no Makefile), verified here with Maven 3.9.16.

$git clone https://github.com/With-ALIF/api-ratelimit-simulator.git
$cd api-ratelimit-simulator
$mvn clean test
$mvn javafx:run
$mvn clean package
What pom.xml (61 lines) actually declares

Java release 17 · 3 deps: javafx-controls + javafx-fxml (21.0.2, compile) and junit-jupiter (5.10.2, test) · 2 plugins: maven-compiler-plugin 3.15.0 (-Xlint:all, showWarnings) and javafx-maven-plugin 0.0.8 with mainClass=com.smartratelimit_abuse.MainApp. No repositories, no profiles, no shade/assembly plugin.

The JAR is not executable

mvn clean package writes target/api-ratelimit-simulator-1.0.jar — a plain jar with no Main-Class manifest, so java -jar will not launch the app. The supported run path is mvn javafx:run (the goal comes from the CLI; the POM only pins the plugin version).

Runtime files

data/*.csv (requests, multi-requests, clients, services) are gitignored and auto-created on first run; sample_data/ must exist because DatasetLoaderTest reads it from the Maven basedir.

System Requirements

RequirementMinimumRecommended
OSWindows 10 / macOS 12 / Ubuntu 20.04Windows 11 / Sonoma / 22.04 LTS
JDKOpenJDK 17OpenJDK 21 LTS (Temurin)
Maven3.8.03.9.6
Display1024 × 7681920 × 1080

How to use the simulator

1Register / Select Client

Pick MobileApp, WebApp, PartnerAPI, SuspiciousBot or register a new tenant.

2Choose a Policy

Fixed Window · Sliding Window · Burst Detection · Abnormal Pattern — swapped through the Strategy interface.

3Generate Traffic

Manual request, 20-request burst, or load sample_requests.csv to replay a recorded session.

4Inspect Reports

Watch live counters, filter the activity table, then open the Abuse Report for block ratios & advice.

Contributed documentation files

FileContents
README.mdFeatures, quick start, team table, architecture ASCII diagram
documentation.md752-line full technical specification (11 chapters)
details.mdAssignment brief, concept overview, required features
index.htmlProject website — architecture, class index, policies, reports, tests and timeline of the simulator
documentation/answer.htmlAssignment answer sheet — objective, UML diagram, worked trace, sample report, OOP mapping
project_file.pdfSubmitted project report
13

UML Diagrams — Class & Sequence

Two standard diagrams for the project report / viva: domain class relationships and a full request sequence.

Fig 13.1 — Domain Class Diagram

Client - clientId: String - name: String + equals() / hashCode() ServiceRequest - clientId: String - service: String - requestType: RequestType - timestamp: LocalDateTime + getFormattedTime(): String RequestLog - clientId: String - requests: List<ServiceRequest> + addRequest(r): void + getRequests(): unmodifiable + getRequestCount() / clear() AbuseReport - clientId: String - level: ViolationLevel - violations: List<String> + addViolation(msg) + setLevel(lvl) [no downgrade] + getRiskScore(): 0..100 «enumeration» RequestType READ | WRITE | UPDATE | DELETE «enumeration» ViolationLevel NORMAL | WARNING | CRITICAL «enumeration» EventType REQUEST | ALLOWED | ... | BLOCKED 1 0..* «analyzed by» belongsTo → Client reads typed by Legend: —› association    - -> dependency    ◆ aggregation    ▸ enum typing
Relationships: RequestLog holds 0..* ServiceRequest · AbuseReport references ViolationLevel · ServiceRequest is typed by RequestType

Fig 13.2 — Sequence Diagram: one manual request (allowed & blocked branches)

ControlPanelView ActionHandler Enforcer RequestLogger ActivityTracker Analyzer + 5 Policies 1. user clicks Send Request 2. processRequest(ServiceRequest) 3. count entries in window 4a. if ALLOWED: logRequest(req) 4b. if BLOCKED: start 3s cooldown · quota = 0 · skip logger 5. RequestResult(blocked, remainingQuota) 6. trackRequest(req, wasBlocked) → totals + successRate 7. analyze(log) — slice last 10s loop [for each of 5 RatePolicy] 8. policy.evaluate(filteredLog, report) 9. addViolation() + setLevel() [monotonic] 10. AbuseReport(level, riskScore) 11. refresh: table · stats · charts · log line 12. persistToCsv() → data/requests.csv  |  Risk badge updated from AbuseReport.getRiskScore()
Fig 13.2 — UML sequence of DashboardActionHandler.handleSendRequest()
14

Requirement Coverage Matrix

Every assignment requirement from details.md mapped to the exact implementing class.

✓Required feature / conceptSourceImplemented byStatus
✓Register API clientsFeature must implementClientRegistryService + ControlPanelViewDONE
✓Record simulated API requestsFeature must implementServiceRequest + RequestLogger + RequestLogServiceDONE
✓Apply rate-limit policiesFeature must implementRatePolicy (5 implementations)DONE
✓Detect excessive requests within time windowsFeature must implementRateLimitEnforcer + SlidingWindowPolicyDONE
✓Generate per-client abuse reportFeature must implementEnhancedReportGenerator + AbuseReportDONE
✓Domain modelling (Client, RequestLog, RatePolicy)Core OOPmodel/* + policy/RatePolicyDONE
✓Encapsulation of counters and thresholdsCore OOPprivate fields + unmodifiable viewsDONE
✓Polymorphism across policiesCore OOPRateLimitAnalyzer.analyze() loopDONE
✓Strategy-like design for evaluationCore OOP«interface» RatePolicyDONE
✓Use of Enums (RequestType, ViolationLevel)Core OOPRequestType, ViolationLevel, EventTypeDONE
✓Data option A: manual entry via JavaFX formData generationControlPanelView + handleSendRequest()DONE
✓Data option B: predefined .txt / .csv datasetData generationDatasetLoader + sample_data/*DONE
✓Data option C: burst generator buttonData generationBurstTrafficGeneratorDONE
✓JavaFX GUITools17 UI classes (views, dialogs, handlers) + main.cssDONE
✓Java Collections (Map, List)ToolsHashMap / LinkedHashMap / ArrayList throughoutDONE
✓Java Time API (LocalDateTime, Duration)ToolsServiceRequest, Enforcer, all policiesDONE
✓File I/O import / export of request logsOptional toolsCsvFileHandler + ReportViewDialog exportDONE
✓Suggested class: Client (clientId, name)Suggested structuremodel/ClientDONE
✓Suggested class: RequestLogSuggested structuremodel/RequestLogDONE
✓Suggested class: RatePolicy interfaceSuggested structurepolicy/RatePolicyDONE
✓Suggested class: FixedWindowPolicySuggested structurepolicy/FixedWindowPolicyDONE
✓Suggested class: SlidingWindowPolicySuggested structurepolicy/SlidingWindowPolicyDONE
✓Suggested class: AbuseReport (violations, severity)Suggested structuremodel/AbuseReportDONE
✓No networking / HTTP / real serversOut of scopezero socket usage in codebaseRESPECTED
✓Bonus: multi-service fan-out simulationBeyond briefmultiservice/* (8 classes)BONUS
✓Bonus: charts, settings, persistence, testsBeyond briefTrafficChartView, SettingsView, CSV, JUnitBONUS
26 / 26
Requirements met
24 / 24
Core + suggested classes
3 / 3
Data generation options
2
Bonus feature groups
15

Development Timeline

14 commits from first skeleton to final submission — told through the files each one touched.

2026-02-03Initial commit — skeletonFirst pom.xml, README.md and MainApp under com.async_alpha: 6 model classes, FixedWindowPolicy + SlidingWindowPolicy + the RatePolicy contract, a compact analyzer, a plain ReportGenerator, RequestLogger, one DashboardView and the base stylesheet.
2026-02-04Fix error and featureThe old ui/DashboardView is replaced by a root-level view; details.md appears; ClientActivityTracker and RateLimitEnforcer land — tracking and admission control become real services.
2026-02-04 / 05Update iterationsThree more detectors arrive — BurstDetectionPolicy, RetryAbusePolicy, AbnormalPatternPolicy — plus an EnhancedReportGenerator and a flat EnhancedDashboardView; DashboardView moves into ui/.
2026-09-04Policies + dashboard UIThe big rewrite: both prototype views are deleted and reborn as 9 focused ui.dashboard classes (table, control panel, action handler, log panel, report dialog …); DatasetLoader and BurstTrafficGenerator join, MainApp moves to com.smartratelimit_abuse, sample_data/ and the first two test classes appear.
2026-09-05Docs + report polishdocumentation.md lands (752 lines, 11 chapters); the OVERALL STATS column alignment is fixed (+218/−21 in the generator), ReportViewDialog grows by 164 lines and the first report-formatting test is written.
2026-09-08Rename project folderPure package rename async_alpha → runtime_crew across every source and test file; the legacy RatePolicy is replaced by a new contract and the old ReportGenerator is deleted.
2026-09-09Graph UI implementedTrafficChartView brings the live 60-second line chart; the enforcer is reworked (+49/−2) to feed it and the stylesheet gains 91 lines.
2026-09-10Settings + bar chartSettingsView exposes max / window / block / burst tunables and BarChartView adds per-service bars; the dashboard is rewired to rebuild on apply.
2026-09-18Restart reload via CSVThe persistence layer lands: ClientRegistryService, CsvFileHandler, CsvParser, CsvRequestLogEntry, RequestLogService — logs survive restarts and the first data/*.csv files are committed.
2026-09-20Stop tracking data CSVs.gitignore gains data/*.csv (runtime data leaves version control) and the whole multiservice package lands — registry, simulator and 5 UI classes including the ServiceManagementDialog — plus the EventType enum.
2026-09-21Multi-service report updatePer-service breakdown in the reports (+74/−13), BarChartView reworked (+102/−19), and the suite reaches its final shape: EnhancedReportGeneratorTest grows to 6 tests and BarChartViewTest adds 5.
2026-09-22Project final — submittedFeature freeze: one last +7-line touch, 15/15 tests green, ready for submission.
16

Algorithm Complexity & Parameter Comparison

Cost of every policy, the enforcer and the analyzer slice, plus the tunables that control them. Notation: N = entries in a client's whole log · n = entries handed to the policy (the analyzer's 10 s slice) · c = clients · R = activity records on screen.

ComponentTimeExtra memoryBoot thresholdWindow it readsEscalates toBest for
FixedWindowPolicyO(n)O(1)count > 53 s (boot)WARNINGSimple quota metering, cheapest option
SlidingWindowPolicyO(n²) worst case
early return on first hit
O(1)count > 53 s (boot)CRITICALStrict limits, boundary-burst protection
BurstDetectionPolicyO(n·k) typical
O(n²) if no gap > window (the break never fires)
O(1)≥ 4 req / 3 s3 s (boot)WARNING → CRITICAL at 3 burstsDoS spikes, flash crowds
AbnormalPatternPolicy3 × O(n)O(n)
intervals[] + type map
>3 night req · >90% one type (≥10) · >70% uniform (≥10)the 10 s slice
no window of its own
WARNING / CRITICALScrapers, bots, off-hours abuse
RetryAbusePolicy2 × O(n)O(1)>5 @ <1000 ms · ≥8 @ ≤2 sadjacent pairs onlyWARNING / CRITICALAggressive retries after rejection
RateLimitEnforcerO(N) per check
stream scans the whole client log
O(c) + O(Ntotal)
blockStartTimes + RequestLogger
max = 10 requests3 s3 s block cooldownReal-time admission control
RateLimitAnalyzer (slicer)O(N) filter + O(n) copyO(n)runs all 5 policies each time10 s hardcoded
RateLimitAnalyzer:23
feeds AbuseReportNarrows the log before detection
Two different numbers, both real: policies read a 3 s window at boot (EnhancedDashboardView:56–58) while the analyzer first trims every log to its last 10 s (RateLimitAnalyzer:23 — an inline literal, no named constant anywhere in the repo).

Runtime tunables (SettingsView)

SettingDefaultEffect
Max Requests10Requests allowed per window before blocking
Time Window (sec)3Window length used by the enforcer
Block Duration (sec)3Cool-down after quota is exhausted
Burst Request Count20Requests synthesized per burst run
Burst Duration (sec)10Time span the burst is spread across
Defaults live in SettingsView:21–25; applying them rebuilds the enforcer & first two policies (EnhancedDashboardView:516–540).

Violation level scale

LevelMeaningRisk score
NORMALUsage within acceptable limits0 (empty list) / violations×15
WARNINGUnusual patterns — monitor the clientviolations×15 + 20
CRITICALSevere abuse — block / rotate credentialsviolations×15 + 40
getRiskScore() = min(violations×15 + {20 | 40}, 100) — the 100 cap applies to every non-empty report; isMoreSevereThan() compares enum ordinals and setLevel() blocks downgrades.

What one 1-second refresh tick costs

refreshClientViews() → O( R·log R ) + O( Σ Nc ) + O( Σ nc2 ) per tick  |  memory O(R)
Single client mode

getRemainingQuota O(N) + analyzer.analyze O(N + n + policies) + table copy/filter O(Rc) + chart re-bucket O(Rc) — lines EnhancedDashboardView:654–673.

ALL_CLIENTS mode

Two per-client loops (quota at :596–599, analyzer at :627–641) re-run the sliding pair scan for every client every second, then setAllRecords sorts R records — ActivityTableView:149.

Timers

Status timer Timeline(1s) at EnhancedDashboardView:68; chart timer 1 s over a 60 s window in 3 s buckets (20 buckets, TrafficChartView:30–31,103). No disk I/O in the tick — loadAll() is in-memory.

CSV writes are off-tick

RequestLogService.append does one open/append/close per request (CsvFileHandler:38–42, O(1) CPU + I/O) with a HashSet of seen ids for de-duplication.

17

Glossary of Key Terms

One-line definitions for every important concept used across the project.

TermDefinitionWhere it lives
Rate LimitingCapping how many requests a client may issue inside a time windowRateLimitEnforcer
Sliding WindowA rolling interval measured from each request forward, so window boundaries cannot be gamedSlidingWindowPolicy
Fixed WindowA discrete bucket of time; simple but vulnerable to bursts straddling the boundaryFixedWindowPolicy
QuotaRemaining requests a client may still send before being blockedgetRemainingQuota()
Block CooldownLockout period after the quota is exhausted; no requests admitted during itblockDuration field
BurstA dense cluster of requests inside a very short span (default ≥4 in 3s)BurstDetectionPolicy
Abuse / AnomalyBehaviour statistically unlike a legitimate client (off-hours, uniform rhythm, one-sided types)AbnormalPatternPolicy
Violation LevelSeverity state NORMAL / WARNING / CRITICAL assigned to a clientViolationLevel enum
Risk Score0–100 numeric risk derived from violation count and levelAbuseReport.getRiskScore()
Strategy PatternEncapsulating interchangeable algorithms behind one interfaceRatePolicy
Admission ControlThe gate that decides ALLOWED vs BLOCKED for every incoming requestprocessRequest()
Event TypeClassified outcome of a request: REQUEST, ALLOWED, RATE_LIMITED, ABUSE_DETECTED, BLOCKEDEventType enum
Multi-Service ModeIssuing one action across N independent API services, each with its own quotaMultiServiceSimulator
Success Rateallowed × 100 / total requests for a clientClientActivity.getSuccessRate()
All Clients ModeAggregated view merging every tenant's records into one dashboardEnhancedDashboardView
Dataset ImportBatch replay of a CSV/TXT traffic log through the same pipelineDatasetLoader
Analyzer 10-second sliceEvery log is first trimmed to its last 10 s (hardcoded literal) before the policies run — the 3 s policy windows sit inside itRateLimitAnalyzer:23
Severity monotonicityA report can only escalate NORMAL→WARNING→CRITICAL, never downgrade; repeated identical violations are stored onceAbuseReport.setLevel() / addViolation()
Composition RootThe single constructor that wires every engine together — the only place boot defaults (10 / 3 s / 3 s) existEnhancedDashboardView:54–60
CSV persistenceAppend-on-request logging with open/append/close per row and a seen-id set; reloaded at boot so history survives restartsRequestLogService / CsvFileHandler
18

FAQ & Troubleshooting

Questions that come up in demos, viva and first-time setup.

Does this app make any real network calls?

No. There are zero sockets, HTTP clients or servers. Every request is a Java object processed in memory with collections and the Java Time API.

Why did my 6th request get blocked?

The enforcer admits at most maxRequests (10 at boot) inside its 3-second window — once the recent count reaches the max, shouldBlock() returns true and starts the 3-second cooldown. The five policies judge separately at their own thresholds (5 per 3 s for Fixed/Sliding) and only raise severity, they never admit or block.

Why is my risk stuck at CRITICAL?

Severity is monotonic by design. AbuseReport.setLevel() refuses to move from CRITICAL to WARNING or NORMAL, so a later benign check cannot erase an earlier critical finding.

Which policy should I select for a demo?

Sliding Window for the strict-limit story, Burst Detection for the DoS story, Abnormal Pattern for the bot/scraping story. Use a burst of 20 requests to show ALLOWED→BLOCKED within seconds.

Where are my data files? They disappeared from git.

Runtime CSVs under data/ are intentionally untracked since the 2026-09-20 timeline entry (.gitignore → data/*.csv). They are re-created with defaults on the next launch.

mvn javafx:run fails — what do I check?

Confirm java -version is 17+, mvn -v is 3.8+, and you are in the project root (where pom.xml lives). Then mvn clean test before running.

Window shows no charts / old data after restart.

Logs reload from data/requests.csv and data/multi_requests.csv. Delete those files if you want a clean slate, then restart.

Can I change the rate limits without recompiling?

Yes — open Settings in the control panel to change max requests, window, block duration and burst parameters, then save. The enforcer and generator are rebuilt from those values.

How do multi-service quotas stay independent?

Each service is keyed as svc_<serviceId> inside the enforcer, so Facebook and Instagram never share a counter even when one client calls both.

How do I present this project quickly?

Use the ▶ Presentation button for the 14-slide deck (arrow keys, Esc to exit), or read the Documentation Map above and jump chapter by chapter.

PRESENTATION · Smart API Rate-Limit & Abuse Simulator
SLIDE 01 · TITLE

Smart API Rate-Limit & Abuse Simulator

A JavaFX desktop simulator that models how cloud gateways, fintech systems and large-scale web services protect APIs — entirely in memory, with zero networking.

Runtime CrewTeam · Group 02
CSE · BRUROOP Coursework
v1.0Java 17 + JavaFX 21
46Main classes
SLIDE 02 · PROBLEM

Why rate-limiting matters

  • Thousands of clients hit the same endpoints concurrently.
  • Without control → DoS, credential stuffing, bot scraping, unfair usage, degraded QoS.
  • Real gateways (Kong, AWS API Gateway, NGINX, Cloudflare) solve it with metering + policy + anomaly engines.
  • Our project rebuilds that internal logic as a teachable, fully observable desktop app.
0Network calls
100%In-memory objects
18CSV audit columns
SLIDE 03 · SCOPE

What is simulated

✓Request lifecycle
✓Rate-limit metering
✓Abuse / anomaly detection
✓Violation reports
✗Real networking
✗HTTP / REST / sockets
✗Real servers & databases
✗Live login / payments

→ It is a request log + rule engine, built only from Java objects and collections.

SLIDE 04 · ARCHITECTURE

Six-tier clean architecture

  • ⑟–① Bootstrap + Presentation (JavaFX) — MainApp → 17 views/handlers (12 dashboard + 5 multi-service)
  • ② Service — enforcer, analyzer, tracker, logger, loaders, report generator (14 classes, 0 JavaFX imports)
  • ③ Policy Strategy — «interface» RatePolicy + 5 algorithms, wired by the 2 composition roots
  • ④ Domain Model — Client, ServiceRequest, RequestLog, AbuseReport, 3 enums (JDK-only imports)
  • ⑤ Storage — CSV persistence under data/, round-tripped through CsvParser

Dependencies always point down — verified by an import-graph scan: 0 cycles, 0 violations (Fig 3.3).

SLIDE 05 · WORKFLOW

Request lifecycle

  • 4 ingestion modes: manual form · burst generator · CSV/TXT dataset · multi-service fan-out
  • Every input becomes an immutable ServiceRequest
  • RateLimitEnforcer.processRequest() compares window count against max quota
  • ALLOWED → write to RequestLogger, decrement quota  |  BLOCKED → start 3s cooldown, quota pinned to 0
  • Both outcomes feed ClientActivityTracker for statistics
  • RateLimitAnalyzer slices the last 10s and runs all 5 policies → AbuseReport
  • Result persisted to CSV + rendered in table, charts, log and report dialogs
SLIDE 06 · POLICIES

Five pluggable policies

5requests / 10s · FIXED
>5any interval · SLIDING
≥4in 3s · BURST
3statistical heuristics
  • FixedWindowPolicy → WARNING  ·  SlidingWindowPolicy → CRITICAL
  • BurstDetectionPolicy → 1+ burst = WARNING, 3+ bursts = CRITICAL
  • AbnormalPatternPolicy → off-hours, type imbalance >90%, uniform bot intervals >70%
  • RetryAbusePolicy → sub-second retries (CRITICAL), 8+ fast chains (WARNING)
  • Severity is monotonic: NORMAL → WARNING → CRITICAL, never downgraded
SLIDE 07 · OOP DESIGN

OOP concepts applied

StrategyRatePolicy interface
SRPone class, one job
Encapsulationunmodifiable views
Enums3 type-safe enums
  • Polymorphism — analyzer runs 5 heterogeneous policies through one contract.
  • Separation of Concerns — UI ≠ services ≠ policies ≠ models.
  • Immutability — Client and ServiceRequest are immutable value objects.
  • Nested domain types — RequestResult, ClientActivity, ActivityRecord.
SLIDE 08 · DASHBOARD

Dashboard components

TopBarbranding header
Controlinputs & actions
Statsmetric cards
Tableactivity log
Line60s traffic chart
Barallowed vs blocked
Loglive console
ReportASCII / HTML dialogs

Single-client and ALL_CLIENTS modes; multi-service mode adds a service column, selector and fan-out simulator.

SLIDE 09 · MULTI-SERVICE

Multi-service extension

  • ServiceRegistry persists services in data/api_services.csv (4 seeded defaults + custom).
  • MultiServiceSimulator.sendRequest() fans one action out to N selected services.
  • Each service gets an isolated quota key svc_<id> → independent rate limits.
  • Event type derived from verdict: ALLOWED, RATE_LIMITED, ABUSE_DETECTED.
  • Every event appended to data/multi_requests.csv with risk score & reason.
  • UI: ServiceSelectorView, ServiceManagementDialog, MultiServiceBarChartView.
SLIDE 10 · DATA & TESTING

Data flow & verification

4CSV data files
2sample datasets
4JUnit test classes
0test failures
  • DatasetLoader — 3 delimiters, 4 timestamp formats, comment/header skipping, error tolerance.
  • Tests: BurstTrafficGeneratorTest · DatasetLoaderTest · EnhancedReportGeneratorTest · BarChartViewTest.
  • Run: mvn clean test → BUILD SUCCESS.
SLIDE 11 · DEMO SCRIPT

Live demo script

  • 1. Run mvn javafx:run → dashboard opens with 4 default clients.
  • 2. Select SuspiciousBot, send 10 manual requests → watch quota drain 10→0.
  • 3. 11th request gets BLOCKED → red row + console warning + cooldown countdown.
  • 4. Click Generate Burst → 20 requests in 10s → block ratio spikes, risk badge escalates.
  • 5. Load sample_requests.csv → replay a mixed session.
  • 6. Open Full Report → ASCII audit with severity, distribution and recommendation.
  • 7. Enable Multi-Service Mode → send one request to Facebook + Telegram + Instagram.
SLIDE 12 · REQUIREMENT COVERAGE

Every requirement covered

26/26Requirements met
3/3Data options
7/7Suggested classes
2Bonus feature groups
  • Features: register clients · record requests · apply policies · detect window abuse · per-client report.
  • OOP: domain modelling, encapsulation, polymorphism, Strategy design, enums.
  • Data: manual form · CSV/TXT dataset · burst generator.
  • Beyond brief: multi-service fan-out, charts, settings, CSV persistence, JUnit tests.
SLIDE 13 · DEVELOPMENT STORY

Built over 14 commits

  • Feb 2026 — skeleton, Maven setup, core model & service layers.
  • Sep 4 — 5 rate-limit policies + full dashboard UI land.
  • Sep 5 — documentation.md + report formatting fixes.
  • Sep 9–10 — line/bar charts and runtime Settings view.
  • Sep 18–21 — CSV restart-reload, git hygiene, multi-service reporting.
  • Sep 22 — final submission, all tests green.
5,160Lines of Java
6Packages
4Test classes
0Open failures
SLIDE 14 · CONCLUSION

Summary & credits

5,160Lines of Java
56Catalogued components
6Packages
5Rate policies
  • Md. Abdullah - Al - Khalid Alif — Architecture, Simulator Engine, Core UI & Integration
  • Mithun Chandra Sarker — Rate-Limiting Policies, Evaluation Strategies
  • Md. Asadujjaman — Activity Tracking, Abuse Detection & Reporting
  • Sojib Ray Shourav — Dataset Ingestion, Testing & Traffic Generation

Begum Rokeya University, Rangpur · CSE · Object-Oriented Programming · Group 02

Copied to clipboard