android comp
This commit is contained in:
1 parent
4ce43a9c41
commit
459188346e
4 files changed
+78
-16
No files matched your search
@@ -15,17 +15,24 @@ class HardwareStatistics:
|
|||||||
self.os_info = None
|
self.os_info = None
|
||||||
self.boot_time = None
|
self.boot_time = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _try(read, fallback=None):
|
||||||
|
try:
|
||||||
|
return read()
|
||||||
|
except Exception:
|
||||||
|
return fallback
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def collect():
|
def collect():
|
||||||
self = HardwareStatistics()
|
self = HardwareStatistics()
|
||||||
self.cpu = self._get_cpu_stats()
|
self.cpu = self._try(self._get_cpu_stats)
|
||||||
self.mem = self._get_memory_stats()
|
self.mem = self._try(self._get_memory_stats)
|
||||||
self.gpu = self._get_gpu_stats()
|
self.gpu = self._try(self._get_gpu_stats, [])
|
||||||
self.disk = self._get_disk_stats()
|
self.disk = self._try(self._get_disk_stats, [])
|
||||||
self.os_info = self._get_os_info()
|
self.os_info = self._try(self._get_os_info)
|
||||||
self.boot_time = datetime.datetime.fromtimestamp(
|
self.boot_time = self._try(
|
||||||
psutil.boot_time()
|
lambda: datetime.datetime.fromtimestamp(psutil.boot_time()).isoformat()
|
||||||
).isoformat()
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
@@ -63,7 +70,8 @@ class HardwareStatistics:
|
|||||||
stats["gpu_mem_total_gb"] = round(sum(g["memory_total"] for g in self.gpu) / 1024, 2)
|
stats["gpu_mem_total_gb"] = round(sum(g["memory_total"] for g in self.gpu) / 1024, 2)
|
||||||
stats["gpu_mem_used_gb"] = round(sum(g["memory_used"] for g in self.gpu) / 1024, 2)
|
stats["gpu_mem_used_gb"] = round(sum(g["memory_used"] for g in self.gpu) / 1024, 2)
|
||||||
|
|
||||||
stats["uptime_hours"] = HardwareScorer.longevity_score(self)
|
if self.boot_time:
|
||||||
|
stats["uptime_hours"] = HardwareScorer.longevity_score(self)
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
@@ -87,7 +95,7 @@ class HardwareStatistics:
|
|||||||
return {
|
return {
|
||||||
"cores": psutil.cpu_count(logical=False),
|
"cores": psutil.cpu_count(logical=False),
|
||||||
"threads": psutil.cpu_count(logical=True),
|
"threads": psutil.cpu_count(logical=True),
|
||||||
"usage_percent": psutil.cpu_percent(interval=0.2)
|
"usage_percent": self._try(lambda: psutil.cpu_percent(interval=0.2))
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_memory_stats(self):
|
def _get_memory_stats(self):
|
||||||
@@ -100,10 +108,7 @@ class HardwareStatistics:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _get_gpu_stats(self):
|
def _get_gpu_stats(self):
|
||||||
try:
|
gpus = GPUtil.getGPUs()
|
||||||
gpus = GPUtil.getGPUs()
|
|
||||||
except Exception:
|
|
||||||
return []
|
|
||||||
if not gpus:
|
if not gpus:
|
||||||
return []
|
return []
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
const STORAGE_KEY = "colony.map.v1";
|
const STORAGE_KEY = "colony.map.v1";
|
||||||
const PAD = 48;
|
const PAD = 48;
|
||||||
const FIT_MS = 260;
|
const FIT_MS = 260;
|
||||||
|
const COMPACT_MAX_WIDTH = 600;
|
||||||
|
|
||||||
const stage = document.getElementById("stage");
|
const stage = document.getElementById("stage");
|
||||||
const svgRoot = document.getElementById("map");
|
const svgRoot = document.getElementById("map");
|
||||||
@@ -149,10 +150,29 @@
|
|||||||
updateControls();
|
updateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function regionView(region) {
|
||||||
|
return C.viewFor({ x: region.x - 40, y: region.y - 40, w: region.w + 80, h: region.h + 80 }, size, 24);
|
||||||
|
}
|
||||||
|
|
||||||
function fitRegion(net) {
|
function fitRegion(net) {
|
||||||
const region = map && map.regionAt.get(net);
|
const region = map && map.regionAt.get(net);
|
||||||
if (!region) return;
|
if (!region) return;
|
||||||
animateTo(C.viewFor({ x: region.x - 40, y: region.y - 40, w: region.w + 80, h: region.h + 80 }, size, 24), true);
|
animateTo(regionView(region), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// On a phone, fitting the whole map shrinks it below the zoom where names and stats are drawn,
|
||||||
|
// so the first view is the region of this node instead. COMPACT_MAX_WIDTH matches the phone
|
||||||
|
// breakpoint in style.css. This only sets `view` and `autoFit`; the caller applies the view afterwards.
|
||||||
|
let startedCompact = false;
|
||||||
|
function startCompact() {
|
||||||
|
if (startedCompact) return;
|
||||||
|
startedCompact = true; // decided once, on the first map: later changes to the window or the topology must not move the view
|
||||||
|
if (size.w > COMPACT_MAX_WIDTH) return;
|
||||||
|
const self = model.nodes.find((node) => node.self);
|
||||||
|
const region = self && map.regionAt.get(self.net);
|
||||||
|
if (!region) return;
|
||||||
|
autoFit = false;
|
||||||
|
view = regionView(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
@@ -482,6 +502,7 @@
|
|||||||
drawNodes();
|
drawNodes();
|
||||||
drawSpokes();
|
drawSpokes();
|
||||||
drawPorts();
|
drawPorts();
|
||||||
|
startCompact();
|
||||||
if (autoFit) fitAll(false);
|
if (autoFit) fitAll(false);
|
||||||
else setView(view, false);
|
else setView(view, false);
|
||||||
drawTrace();
|
drawTrace();
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Colony</title>
|
<title>Colony</title>
|
||||||
|
<script>
|
||||||
|
/* The Android app asks for ?theme=dark: a WebView reports the theme of its host app, not the phone's setting. */
|
||||||
|
const theme = new URLSearchParams(location.search).get("theme");
|
||||||
|
if (theme === "dark" || theme === "light") document.documentElement.dataset.theme = theme;
|
||||||
|
</script>
|
||||||
<link rel="stylesheet" href="/static/style.css">
|
<link rel="stylesheet" href="/static/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root:not([data-theme="light"]) {
|
||||||
|
color-scheme: dark;
|
||||||
--bg: #12161c;
|
--bg: #12161c;
|
||||||
--card: #1b2129;
|
--card: #1b2129;
|
||||||
--text: #e6eaf0;
|
--text: #e6eaf0;
|
||||||
@@ -38,6 +39,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root[data-theme="dark"] {
|
||||||
|
color-scheme: dark;
|
||||||
|
--bg: #12161c;
|
||||||
|
--card: #1b2129;
|
||||||
|
--text: #e6eaf0;
|
||||||
|
--muted: #93a0b3;
|
||||||
|
--line: #313a47;
|
||||||
|
--down: #6b7686;
|
||||||
|
--track: #2a3340;
|
||||||
|
--panel: rgba(27, 33, 41, 0.92);
|
||||||
|
--warn: #ffb04a;
|
||||||
|
--crit: #ff6b6b;
|
||||||
|
--n0: #6c9cff;
|
||||||
|
--n1: #3cc7c7;
|
||||||
|
--n2: #ab8cff;
|
||||||
|
--n3: #ff7cc8;
|
||||||
|
--n4: #e0b04a;
|
||||||
|
--n5: #8fd06a;
|
||||||
|
}
|
||||||
|
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
|
|
||||||
html, body { height: 100%; }
|
html, body { height: 100%; }
|
||||||
@@ -196,3 +217,13 @@ p { margin: 4px 0; }
|
|||||||
.swatch.none { background: transparent; border: 2px dashed var(--muted); }
|
.swatch.none { background: transparent; border: 2px dashed var(--muted); }
|
||||||
|
|
||||||
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
||||||
|
|
||||||
|
/* Phones: the desktop sizes are small on a 400px screen, so the page text and touch targets grow. */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
body { font-size: 16px; }
|
||||||
|
header { padding: 0 12px 6px; }
|
||||||
|
h1 { font-size: 24px; }
|
||||||
|
.alert, .route, .muted, .legend { font-size: 14px; }
|
||||||
|
.legend { max-width: calc(100% - 24px); }
|
||||||
|
.legend, .legend-open { bottom: 64px; }
|
||||||
|
}
|
||||||
Reference in new issue
Block a user