- 虚拟时钟:实训台时钟面板可拨时间、1×/10×/60× 倍速、恢复真实时间;编译时把 DateTime.Now / Today / UtcNow 改写成 SimClock;评分规则加 clock 步骤 - 项目资源(Properties.Resources):平台素材库(自绘开关图片、合成门铃声),"项目资源"对话框勾选, 平台生成 Properties/Resources.Designer.cs;设计器图片框的"图片"属性可选资源;程序目录下的 Resources 指向素材库;未添加资源时给中文提示 - Windows Media Player(AxWMPLib):设置 URL 自动播放、Ctlcontrols.play/stop,浏览器里播放声音, 实训台加广播喇叭;编译时给窗体嵌空资源,OcxState 取到 null 不报错;图片和声音统一按内容缓存(blob) - TrackBar:拖动、点轨道、方向键,先 ValueChanged 再 Scroll;设计器加"滑动条""媒体播放器" - 评分规则加 value、media 检查;示例项目 7 任务 1–3(修正书上开关灯判断写反、漏填串口列表) - 修正:Properties/ 下的资源类不当作窗体;带命名空间的 System.AppDomain.CurrentDomain.BaseDirectory 放行 - 测试:虚拟时钟、TrackBar、项目 7 示例评分、作业起点带资源类 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.7 KiB
C#
47 lines
1.7 KiB
C#
using System;
|
||
using System.ComponentModel;
|
||
using System.Globalization;
|
||
using System.Text.Json.Nodes;
|
||
|
||
namespace Sim.Host;
|
||
|
||
/// <summary>
|
||
/// 虚拟时钟(实训台上可以拨时间、调倍速;教材项目 7 按时刻切换情景模式)。
|
||
/// 编译时把学生代码里的 DateTime.Now / Today / UtcNow 改写成这里的属性(见 Sim.Runner/ClockRewriter.cs)。
|
||
/// 没有拨过时就是真实时间。
|
||
/// </summary>
|
||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||
public static class SimClock
|
||
{
|
||
private sealed record Setting(DateTime Wall, long RealAt, double Speed);
|
||
|
||
private static volatile Setting? _setting;
|
||
|
||
public static DateTime Now
|
||
{
|
||
get
|
||
{
|
||
var setting = _setting;
|
||
if (setting == null) return DateTime.Now;
|
||
var elapsed = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - setting.RealAt;
|
||
return setting.Wall.AddMilliseconds(elapsed * setting.Speed);
|
||
}
|
||
}
|
||
|
||
public static DateTime Today => Now.Date;
|
||
|
||
public static DateTime UtcNow => Now.ToUniversalTime();
|
||
|
||
/// <summary>平台内部使用:应用服务器推送的 {"wall":"2024-01-16T06:40:00","realAt":…,"speed":60},null 恢复真实时间</summary>
|
||
public static void Update(JsonNode? clock)
|
||
{
|
||
if (clock is not JsonObject json
|
||
|| !DateTime.TryParseExact((string?)json["wall"], "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var wall))
|
||
{
|
||
_setting = null;
|
||
return;
|
||
}
|
||
_setting = new Setting(DateTime.SpecifyKind(wall, DateTimeKind.Local), (long?)json["realAt"] ?? 0, (double?)json["speed"] ?? 1);
|
||
}
|
||
}
|