display run duration

This commit is contained in:
2026-02-20 08:52:31 -08:00
parent a238793cdc
commit 3dea810a50
4 changed files with 51 additions and 21 deletions

View File

@@ -1,9 +1,10 @@
use strafesnet_roblox_bot_file::v0;
use strafesnet_common::physics::{Time as PhysicsTime};
/// A loaded bot file.
pub struct CompleteBot{
//Instructions
timelines:strafesnet_roblox_bot_file::v0::Block,
timelines:v0::Block,
time_base:PhysicsTime,
duration:PhysicsTime,
}
@@ -11,8 +12,8 @@ impl CompleteBot{
pub(crate) const CAMERA_OFFSET:glam::Vec3=glam::vec3(0.0,2.0,0.0);
pub fn new(
data:&[u8],
)->Result<Self,strafesnet_roblox_bot_file::v0::Error>{
let timelines=strafesnet_roblox_bot_file::v0::read_all_to_block(std::io::Cursor::new(data))?;
)->Result<Self,v0::Error>{
let timelines=v0::read_all_to_block(std::io::Cursor::new(data))?;
let first=timelines.output_events.first().unwrap();
let last=timelines.output_events.last().unwrap();
Ok(Self{
@@ -27,7 +28,21 @@ impl CompleteBot{
pub const fn duration(&self)->PhysicsTime{
self.duration
}
pub const fn timelines(&self)->&strafesnet_roblox_bot_file::v0::Block{
pub const fn timelines(&self)->&v0::Block{
&self.timelines
}
pub fn run_duration(&self,mode_id:v0::ModeID)->Option<PhysicsTime>{
let mut it=self.timelines.run_events.iter().rev();
let end=it.find_map(|event|match &event.event{
v0::RunEvent::Finish(run_start_event) if run_start_event.mode==mode_id=>Some(event.time),
_=>None,
})?;
let start=it.find_map(|event|match &event.event{
v0::RunEvent::Start(run_start_event) if run_start_event.mode==mode_id=>Some(event.time),
_=>None,
})?;
let start=crate::time::from_float(start).unwrap();
let end=crate::time::from_float(end).unwrap();
Some(end-start)
}
}

View File

@@ -1,5 +1,6 @@
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;
use strafesnet_roblox_bot_file::v0;
use strafesnet_roblox_bot_player::{bot,map,head,time,graphics};
use strafesnet_graphics::setup;
use strafesnet_common::physics::Time as PhysicsTime;
@@ -72,6 +73,11 @@ impl CompleteBot{
pub fn duration(&self)->f64{
self.bot.duration().get() as f64/PhysicsTime::ONE_SECOND.get() as f64
}
#[wasm_bindgen]
pub fn run_duration(&self,mode_id:u32)->Option<f64>{
let mode=v0::ModeID(mode_id);
Some(self.bot.run_duration(mode)?.get() as f64/PhysicsTime::ONE_SECOND.get() as f64)
}
}
#[wasm_bindgen]
@@ -110,18 +116,18 @@ impl PlaybackHead{
pub fn get_run_time(&self,bot:&CompleteBot,time:f64,mode_id:u32)->Option<f64>{
let time=time::from_float(time).unwrap();
let time=self.head.time(&bot.bot,time);
let mode=strafesnet_roblox_bot_file::v0::ModeID(mode_id);
let mode=v0::ModeID(mode_id);
let run_time=self.head.state().get_run(mode)?.time(time);
Some(run_time.get() as f64/strafesnet_common::run::Time::ONE_SECOND.get() as f64)
}
#[wasm_bindgen]
pub fn is_run_in_progress(&self,mode_id:u32)->Option<bool>{
let mode=strafesnet_roblox_bot_file::v0::ModeID(mode_id);
let mode=v0::ModeID(mode_id);
Some(self.head.state().get_run(mode)?.is_in_progress())
}
#[wasm_bindgen]
pub fn is_run_finished(&self,mode_id:u32)->Option<bool>{
let mode=strafesnet_roblox_bot_file::v0::ModeID(mode_id);
let mode=v0::ModeID(mode_id);
Some(self.head.state().get_run(mode)?.is_finished())
}
}

View File

@@ -23,26 +23,32 @@
width: 100%;
height: 100%;
}
.hud {
position: fixed;
bottom: 10px;
left: 10px;
display: flex;
flex-direction: column; /* stack vertically */
gap: 4px; /* space between timers */
}
.timer {
background: #000;
color: #fff;
padding: 4px 8px;
font-family: sans-serif;
font-size: 14px;
border-radius: 3px;
}
</style>
<script defer src="player.js" type="module"></script>
<script defer type="module" src="iframe-helper.js"></script>
</head>
<body>
<canvas id="viewport"> </canvas>
<div
id="timer"
style="
position: fixed;
bottom: 10px;
left: 10px;
background: #000;
color: #fff;
padding: 4px 8px;
font-family: sans-serif;
font-size: 14px;
"
>
00:00:00
<div class="hud">
<div id="duration" class="timer">00:00:00</div>
<div id="timer" class="timer">00:00:00</div>
</div>
</body>
</html>

View File

@@ -21,6 +21,7 @@ graphics.change_map(map);
const startTime = performance.now();
const timer = document.getElementById("timer");
const duration = document.getElementById("duration");
const MODE_MAIN = 0;
function timer_text(t) {
@@ -31,6 +32,8 @@ function timer_text(t) {
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}.${String(ms).padStart(3, "0")}`;
}
duration.textContent = timer_text(bot.run_duration(MODE_MAIN));
function animate(now) {
const elapsedMs = now - startTime;
const elapsedSec = elapsedMs / 1000; // wasm expects seconds