|
|
|
|
@ -1,375 +1,23 @@
@@ -1,375 +1,23 @@
|
|
|
|
|
<!DOCTYPE html> |
|
|
|
|
<html lang="en"> |
|
|
|
|
<head> |
|
|
|
|
|
|
|
|
|
<head> |
|
|
|
|
<meta charset="UTF-8"> |
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
|
|
<title>System Design Game</title> |
|
|
|
|
<link rel="stylesheet" type="text/css" href="/static/style.css" /> |
|
|
|
|
</head> |
|
|
|
|
<body> |
|
|
|
|
</head> |
|
|
|
|
|
|
|
|
|
<body> |
|
|
|
|
<div id="page-container"> |
|
|
|
|
<div id="sd-header"> |
|
|
|
|
<h1 class="header-text">System Design Game</h1> |
|
|
|
|
{{ if and .Username .Avatar }} |
|
|
|
|
<div class="userbox"> |
|
|
|
|
<img src="{{ .Avatar }}" class="avatar" /> |
|
|
|
|
<span class="username">{{ .Username }}</span> |
|
|
|
|
</div> |
|
|
|
|
{{ else }} |
|
|
|
|
<a href="/login" id="github-login-btn"> |
|
|
|
|
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg" alt="GitHub Logo"> |
|
|
|
|
Login with GitHub |
|
|
|
|
</a> |
|
|
|
|
{{ end }} |
|
|
|
|
</div> |
|
|
|
|
{{ template "header" . }} |
|
|
|
|
<div id="main-content"> |
|
|
|
|
<div id="challenge-container"> |
|
|
|
|
<h2 class="sidebar-title">Challenges</h2> |
|
|
|
|
|
|
|
|
|
<ul class="challenge-list"> |
|
|
|
|
{{range .Levels}} |
|
|
|
|
<li class="challenge-item {{if and (eq .Name $.Level.Name) (eq .Difficulty $.Level.Difficulty)}}active{{end}}"> |
|
|
|
|
<div class="challenge-name">{{.Name}}</div> |
|
|
|
|
<div class="challenge-difficulty {{.Difficulty}}">{{.Difficulty}}</div> |
|
|
|
|
</li> |
|
|
|
|
{{end}} |
|
|
|
|
</ul> |
|
|
|
|
</div> |
|
|
|
|
<div id="canvas-wrapper"> |
|
|
|
|
<input type="radio" id="tab1" name="tab" checked> |
|
|
|
|
<input type="radio" id="tab2" name="tab"> |
|
|
|
|
<input type="radio" id="tab3" name="tab"> |
|
|
|
|
|
|
|
|
|
<div class="tabs"> |
|
|
|
|
<div class="tab-labels"> |
|
|
|
|
<label for="tab1">Requirements</label> |
|
|
|
|
<label for="tab2">Design</label> |
|
|
|
|
<label for="tab3">Metrics</label> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<!-- Requirements --> |
|
|
|
|
<div id="content1" class="tab-content"> |
|
|
|
|
{{ if .Level.InterviewerRequirements }} |
|
|
|
|
<div class="requirements-section"> |
|
|
|
|
<h3>Interviewer Requirements</h3> |
|
|
|
|
<ul class="requirements-list"> |
|
|
|
|
{{ range .Level.InterviewerRequirements }} |
|
|
|
|
<li class="requirement-item">{{ . }}</li> |
|
|
|
|
{{ end }} |
|
|
|
|
</ul> |
|
|
|
|
</div> |
|
|
|
|
{{ end }} |
|
|
|
|
|
|
|
|
|
{{ if .Level.FunctionalRequirements }} |
|
|
|
|
<div class="requirements-section"> |
|
|
|
|
<h3>Functional Requirements</h3> |
|
|
|
|
<ul class="requirements-list"> |
|
|
|
|
{{ range .Level.FunctionalRequirements }} |
|
|
|
|
<li class="requirement-item">{{ . }}</li> |
|
|
|
|
{{ end }} |
|
|
|
|
</ul> |
|
|
|
|
</div> |
|
|
|
|
{{ end }} |
|
|
|
|
|
|
|
|
|
{{ if .Level.NonFunctionalRequirements }} |
|
|
|
|
<div class="requirements-section"> |
|
|
|
|
<h3>Non-Functional Requirements</h3> |
|
|
|
|
<ul class="requirements-list"> |
|
|
|
|
{{ range .Level.NonFunctionalRequirements }} |
|
|
|
|
<li class="requirement-item">{{ . }}</li> |
|
|
|
|
{{ end }} |
|
|
|
|
</ul> |
|
|
|
|
</div> |
|
|
|
|
{{ end }} |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<!-- Design--> |
|
|
|
|
<div id="content2" class="tab-content"> |
|
|
|
|
<div id="sidebar"> |
|
|
|
|
<div class="component-icon" draggable="true" data-type="user"> |
|
|
|
|
user |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="loadBalancer"> |
|
|
|
|
load balancer |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="webserver"> |
|
|
|
|
webserver |
|
|
|
|
</div> |
|
|
|
|
<div class="component-icon" draggable="true" data-type="database"> |
|
|
|
|
database |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="cache"> |
|
|
|
|
cache |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="messageQueue"> |
|
|
|
|
message queue |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="cdn"> |
|
|
|
|
CDN |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="microservice"> |
|
|
|
|
microservice node |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="data pipeline"> |
|
|
|
|
data pipeline |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="monitoring/alerting"> |
|
|
|
|
monitoring/alerting |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="component-icon" draggable="true" data-type="third party service"> |
|
|
|
|
third-party service |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div id="canvas-container"> |
|
|
|
|
<div id="connection-modal" style="display: none;" class="modal"> |
|
|
|
|
<div class="modal-content"> |
|
|
|
|
<h3>Create Connection</h3> |
|
|
|
|
<label> |
|
|
|
|
Label: |
|
|
|
|
<input type="text" id="connection-label" value="Read traffic"> |
|
|
|
|
</label> |
|
|
|
|
<label> |
|
|
|
|
Protocol: |
|
|
|
|
<select id="connection-protocol"> |
|
|
|
|
<option>HTTP</option> |
|
|
|
|
<option>HTTPS</option> |
|
|
|
|
<option>gRPC</option> |
|
|
|
|
<option>WebSocket</option> |
|
|
|
|
<option>GraphQL</option> |
|
|
|
|
<option>Kafka</option> |
|
|
|
|
<option>AMQP</option> |
|
|
|
|
<option>MQTT</option> |
|
|
|
|
<option>SQL</option> |
|
|
|
|
<option>NoSQL</option> |
|
|
|
|
<option>Redis</option> |
|
|
|
|
<option>TLS</option> |
|
|
|
|
</select> |
|
|
|
|
</label> |
|
|
|
|
<label style="margin-top: 10px;"> |
|
|
|
|
<input type="checkbox" id="connection-tls"> |
|
|
|
|
Enable TLS (encryption) |
|
|
|
|
</label> |
|
|
|
|
<label for="connection-capacity">Capacity Limit (RPS):</label> |
|
|
|
|
<input type="number" id="connection-capacity" value="1000" min="1" /> |
|
|
|
|
<div class="modal-actions"> |
|
|
|
|
<button id="connection-save">Save</button> |
|
|
|
|
<button id="connection-cancel">Cancel</button> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<div id="canvas-toolbar"> |
|
|
|
|
<button id="arrow-tool-btn" class="toolbar-btn">Arrow Tool</button> |
|
|
|
|
</div> |
|
|
|
|
<div id="info-panel"> |
|
|
|
|
<div id="constraints-panel"> |
|
|
|
|
<div class="panel-title">level constraints</div> |
|
|
|
|
<div class="panel-metric"><span class="label">🎯 target rps:</span> <span id="constraint-rps">{{.Level.TargetRPS}}</span></div> |
|
|
|
|
<div class="panel-metric"><span class="label">⏱️ max p95 latency:</span> <span id="constraint-latency">{{.Level.MaxP95LatencyMs}}ms</span></div> |
|
|
|
|
<div class="panel-metric"><span class="label">💸 max cost:</span> <span id="constraint-cost">${{.Level.MaxMonthlyUSD}}</span></div> |
|
|
|
|
<div class="panel-metric"><span class="label">🔒 availability:</span> <span id="constraint-availability">{{printf "%.2f" .Level.RequiredAvailabilityPct}}%</span></div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<svg id="canvas"> |
|
|
|
|
<defs> |
|
|
|
|
<marker id="arrowhead-start" markerWidth="10" markerHeight="7" refX="0" refY="3.5" |
|
|
|
|
orient="auto" markerUnits="strokeWidth"> |
|
|
|
|
<path d="M10 0 L0 3.5 L10 7" fill="#ccc" /> |
|
|
|
|
</marker> |
|
|
|
|
<marker id="arrowhead-end" markerWidth="10" markerHeight="7" refX="10" refY="3.5" |
|
|
|
|
orient="auto" markerUnits="strokeWidth"> |
|
|
|
|
<path d="M0 0 L10 3.5 L0 7" fill="#ccc" /> |
|
|
|
|
</marker> |
|
|
|
|
</defs> |
|
|
|
|
</svg> |
|
|
|
|
<div id="node-props-panel"> |
|
|
|
|
<h3>node properties</h3> |
|
|
|
|
<div id="label-group" data-group="label-group"> |
|
|
|
|
<label>label:</label> |
|
|
|
|
<input type="text" name="label" /> |
|
|
|
|
</div> |
|
|
|
|
<div id="db-group" class="prop-group" data-group="db-group"> |
|
|
|
|
<label>replication factor:<input type="number" name="replication" min="1" step="1" /></label> |
|
|
|
|
</div> |
|
|
|
|
<div id="cache-group" class="prop-group" data-group="cache-group"> |
|
|
|
|
<label>cache ttl (secs):<input type="number" name="cacheTTL" min="0" step="60" /></label> |
|
|
|
|
<label>Max Entries: <input name="maxEntries" type="number" /></label> |
|
|
|
|
<label>Eviction Policy: |
|
|
|
|
<select name="evictionPolicy"> |
|
|
|
|
<option value="LRU">LRU</option> |
|
|
|
|
<option value="LFU">LFU</option> |
|
|
|
|
<option value="Random">Random</option> |
|
|
|
|
</select> |
|
|
|
|
</label> |
|
|
|
|
</div> |
|
|
|
|
<div id="compute-group" data-group="compute-group" class="prop-group"> |
|
|
|
|
<label>CPU Cores:</label> |
|
|
|
|
<input type="number" name="cpu" min="1" /> |
|
|
|
|
|
|
|
|
|
<label>RAM (GB):</label> |
|
|
|
|
<input type="number" name="ramGb" min="1" /> |
|
|
|
|
|
|
|
|
|
<label>RPS Capacity:</label> |
|
|
|
|
<input type="number" name="rpsCapacity" min="1" /> |
|
|
|
|
{{ template "challenges" . }} |
|
|
|
|
|
|
|
|
|
<label>Monthly Cost (USD):</label> |
|
|
|
|
<input type="number" name="monthlyCostUsd" min="0" /> |
|
|
|
|
</div> |
|
|
|
|
<div id="lb-group" data-group="lb-group" class="prop-group"> |
|
|
|
|
<label>Algorithm</label> |
|
|
|
|
<select name="algorithm"> |
|
|
|
|
<option value="round-robin">Round Robin</option> |
|
|
|
|
<option value="least-connections">Least Connections</option> |
|
|
|
|
</select> |
|
|
|
|
</div> |
|
|
|
|
<div id="mq-group" data-group="mq-group" class="prop-group"> |
|
|
|
|
<label>Queue Capacity (,ax Messages that can be held in que)</label> |
|
|
|
|
<input type="number" name="queueCapacity" min="1" /> |
|
|
|
|
|
|
|
|
|
<label>Retention Time (seconds)</label> |
|
|
|
|
<input type="number" name="retentionSeconds" min="1" /> |
|
|
|
|
</div> |
|
|
|
|
<div id="cdn-group" data-group="cdn-group" class="prop-group"> |
|
|
|
|
<label>TTL (seconds)</label> |
|
|
|
|
<input type="number" name="ttl" min="1" /> |
|
|
|
|
|
|
|
|
|
<label>Geo Replication</label> |
|
|
|
|
<select name="geoReplication"> |
|
|
|
|
<option value="global">Global</option> |
|
|
|
|
<option value="regional">Regional</option> |
|
|
|
|
<option value="custom">Custom</option> |
|
|
|
|
</select> |
|
|
|
|
|
|
|
|
|
<label>Caching Strategy</label> |
|
|
|
|
<select name="cachingStrategy"> |
|
|
|
|
<option value="cache-first">Cache First</option> |
|
|
|
|
<option value="network-first">Network First</option> |
|
|
|
|
<option value="stale-while-revalidate">Stale While Revalidate</option> |
|
|
|
|
</select> |
|
|
|
|
|
|
|
|
|
<label>Compression</label> |
|
|
|
|
<select name="compression"> |
|
|
|
|
<option value="brotli">Brotli</option> |
|
|
|
|
<option value="gzip">Gzip</option> |
|
|
|
|
<option value="none">None</option> |
|
|
|
|
</select> |
|
|
|
|
|
|
|
|
|
<label>HTTP/2 Support</label> |
|
|
|
|
<select name="http2"> |
|
|
|
|
<option value="enabled">Enabled</option> |
|
|
|
|
<option value="disabled">Disabled</option> |
|
|
|
|
</select> |
|
|
|
|
</div> |
|
|
|
|
<div id="microservice-group" data-group="microservice-group" class="prop-group"> |
|
|
|
|
<label> |
|
|
|
|
Instance Count: |
|
|
|
|
<input type="number" name="instanceCount" value="3" min="1" /> |
|
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
CPU (vCPUs): |
|
|
|
|
<input type="number" name="cpu" value="2" min="1" /> |
|
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
RAM (GB): |
|
|
|
|
<input type="number" name="ramGb" value="4" min="1" /> |
|
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
RPS Capacity: |
|
|
|
|
<input type="number" name="rpsCapacity" value="150" min="1" /> |
|
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
Monthly Cost (USD): |
|
|
|
|
<input type="number" name="monthlyUsd" value="18" min="0" step="1" /> |
|
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
Scaling Strategy: |
|
|
|
|
<select name="scalingStrategy"> |
|
|
|
|
<option value="auto" selected>Auto</option> |
|
|
|
|
<option value="manual">Manual</option> |
|
|
|
|
</select> |
|
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
API Version: |
|
|
|
|
<input type="text" name="apiVersion" value="v1" /> |
|
|
|
|
</label> |
|
|
|
|
</div> |
|
|
|
|
<div id="datapipeline-group" data-group="pipeline-group" class="prop-group"> |
|
|
|
|
<label>Batch Size</label> |
|
|
|
|
<input type="number" name="batchSize" min="1" /> |
|
|
|
|
|
|
|
|
|
<label>Schedule</label> |
|
|
|
|
<select name="schedule"> |
|
|
|
|
<option value="realtime">Real-time</option> |
|
|
|
|
<option value="hourly">Hourly</option> |
|
|
|
|
<option value="daily">Daily</option> |
|
|
|
|
<option value="weekly">Weekly</option> |
|
|
|
|
</select> |
|
|
|
|
|
|
|
|
|
<label>Transformations</label> |
|
|
|
|
<select name="transformations"> |
|
|
|
|
<option value="normalize">Normalize</option> |
|
|
|
|
<option value="dedupe">Dedupe</option> |
|
|
|
|
<option value="filter">Filter</option> |
|
|
|
|
<option value="enrich">Enrich</option> |
|
|
|
|
<option value="aggregate">Aggregate</option> |
|
|
|
|
</select> |
|
|
|
|
|
|
|
|
|
<label>Destination</label> |
|
|
|
|
<input type="text" name="destination" placeholder="e.g. data warehouse" /> |
|
|
|
|
</div> |
|
|
|
|
<div id="monitor-group" data-group="monitor-group" class="prop-group"> |
|
|
|
|
<label>Monitoring Tool</label> |
|
|
|
|
<select name="tool"> |
|
|
|
|
<option value="Prometheus">Prometheus</option> |
|
|
|
|
<option value="Datadog">Datadog</option> |
|
|
|
|
<option value="New Relic">New Relic</option> |
|
|
|
|
<option value="Grafana Cloud">Grafana Cloud</option> |
|
|
|
|
</select> |
|
|
|
|
|
|
|
|
|
<label>Alert Threshold (%)</label> |
|
|
|
|
<input type="number" name="alertThreshold" min="0" max="100" /> |
|
|
|
|
</div> |
|
|
|
|
<div id="third-party-group" data-group="third-party-group" class="prop-group"> |
|
|
|
|
<label>Provider</label> |
|
|
|
|
<input type="text" name="provider" /> |
|
|
|
|
|
|
|
|
|
<label>Latency (ms)</label> |
|
|
|
|
<input type="number" name="latency" min="0" /> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- PUT NEW COMPONENTS BEFORE THIS BUTTON --> |
|
|
|
|
<button id="node-props-save" disabled>save</button> |
|
|
|
|
</div> |
|
|
|
|
<div id="bottom-panel"> |
|
|
|
|
<button id="run-button" disabled>Test Design</button> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<!-- Metrics--> |
|
|
|
|
<div id="content3" class="tab-content">This is Tab 3 content.</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{{ template "canvas" . }} |
|
|
|
|
|
|
|
|
|
{{ template "chat" . }} |
|
|
|
|
<script type="module" src="/static/index.js"></script> |
|
|
|
|
</body> |
|
|
|
|
</html> |
|
|
|
|
</body> |
|
|
|
|
|
|
|
|
|
</html> |
|
|
|
|
|