chore: HERV 통합 저장소 재초기화 커밋
손상된 .git 히스토리(missing tree)로 재초기화 후 작업트리 전체 커밋. .claude/ 만 제외(로컬 에이전트 설정). 구 저장소 백업(.git_corrupt_backup/) 포함. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using ErvDashboard.Model;
|
||||
|
||||
namespace ErvDashboard
|
||||
{
|
||||
// 스마트수면 시간설정 팝업 (원형 다이얼). 시작/종료 시각을 설정 → 적용 시 메인이 종료 시각에 자동 해제 예약.
|
||||
// 대시보드 전용(ERV 프로토콜 무관). 시각은 자정 기준 분(0~1439, 30분 단위).
|
||||
public partial class SmartSleepWindow : Window
|
||||
{
|
||||
readonly MainWindow _owner;
|
||||
readonly DashboardState _state;
|
||||
|
||||
const double CX = 130, CY = 130, R = 104; // DialCanvas(260x260) 중심/반지름
|
||||
|
||||
int _startMin, _endMin;
|
||||
bool _dragStart, _dragEnd, _updating;
|
||||
|
||||
public SmartSleepWindow(MainWindow owner, DashboardState state)
|
||||
{
|
||||
InitializeComponent();
|
||||
_owner = owner;
|
||||
_state = state;
|
||||
_startMin = state.SleepStartMin;
|
||||
_endMin = state.SleepEndMin;
|
||||
|
||||
for (int m = 0; m < 1440; m += 30)
|
||||
{
|
||||
StartCombo.Items.Add(new ComboBoxItem { Content = DashboardState.FmtTime(m), Tag = m });
|
||||
EndCombo.Items.Add(new ComboBoxItem { Content = DashboardState.FmtTime(m), Tag = m });
|
||||
}
|
||||
StartCombo.SelectionChanged += StartCombo_Changed;
|
||||
EndCombo.SelectionChanged += EndCombo_Changed;
|
||||
|
||||
UpdateDial();
|
||||
}
|
||||
|
||||
// ===== 다이얼/콤보 갱신 =====
|
||||
void UpdateDial()
|
||||
{
|
||||
_updating = true;
|
||||
SleepArc.Data = BuildArc(_startMin, _endMin);
|
||||
PositionHandle(StartHandle, _startMin);
|
||||
PositionHandle(EndHandle, _endMin);
|
||||
StartRun.Text = DashboardState.FmtTime(_startMin);
|
||||
EndRun.Text = DashboardState.FmtTime(_endMin);
|
||||
StartCombo.SelectedIndex = _startMin / 30;
|
||||
EndCombo.SelectedIndex = _endMin / 30;
|
||||
_updating = false;
|
||||
}
|
||||
|
||||
Geometry BuildArc(int s, int e)
|
||||
{
|
||||
Point p0 = Polar(s / 1440.0 * 360.0);
|
||||
Point p1 = Polar(e / 1440.0 * 360.0);
|
||||
double sweep = ((e - s + 1440) % 1440) / 1440.0 * 360.0;
|
||||
var fig = new System.Windows.Media.PathFigure { StartPoint = p0, IsClosed = false };
|
||||
fig.Segments.Add(new ArcSegment(p1, new Size(R, R), 0, sweep > 180.0, SweepDirection.Clockwise, true));
|
||||
var g = new PathGeometry();
|
||||
g.Figures.Add(fig);
|
||||
return g;
|
||||
}
|
||||
|
||||
static Point Polar(double angleDeg) // 0°=위, 시계방향
|
||||
{
|
||||
double t = angleDeg * Math.PI / 180.0;
|
||||
return new Point(CX + R * Math.Sin(t), CY - R * Math.Cos(t));
|
||||
}
|
||||
|
||||
static void PositionHandle(FrameworkElement h, int min)
|
||||
{
|
||||
Point p = Polar(min / 1440.0 * 360.0);
|
||||
Canvas.SetLeft(h, p.X - h.Width / 2);
|
||||
Canvas.SetTop(h, p.Y - h.Height / 2);
|
||||
}
|
||||
|
||||
static int AngleToMin(Point p)
|
||||
{
|
||||
double ang = Math.Atan2(p.X - CX, -(p.Y - CY)) * 180.0 / Math.PI; // 0=위, 시계방향
|
||||
if (ang < 0) ang += 360;
|
||||
int min = (int)Math.Round(ang / 360.0 * 1440.0 / 30.0) * 30;
|
||||
return ((min % 1440) + 1440) % 1440;
|
||||
}
|
||||
|
||||
// ===== 드래그 =====
|
||||
void StartHandle_Down(object sender, MouseButtonEventArgs e) { _dragStart = true; StartHandle.CaptureMouse(); e.Handled = true; }
|
||||
void EndHandle_Down(object sender, MouseButtonEventArgs e) { _dragEnd = true; EndHandle.CaptureMouse(); e.Handled = true; }
|
||||
|
||||
void Handle_Move(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!_dragStart && !_dragEnd) return;
|
||||
int min = AngleToMin(e.GetPosition(DialCanvas));
|
||||
if (_dragStart) _startMin = min; else _endMin = min;
|
||||
UpdateDial();
|
||||
}
|
||||
|
||||
void Handle_Up(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
_dragStart = _dragEnd = false;
|
||||
(sender as UIElement)?.ReleaseMouseCapture();
|
||||
}
|
||||
|
||||
// ===== 콤보 =====
|
||||
void StartCombo_Changed(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_updating || StartCombo.SelectedItem is not ComboBoxItem it) return;
|
||||
_startMin = (int)it.Tag;
|
||||
UpdateDial();
|
||||
}
|
||||
|
||||
void EndCombo_Changed(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_updating || EndCombo.SelectedItem is not ComboBoxItem it) return;
|
||||
_endMin = (int)it.Tag;
|
||||
UpdateDial();
|
||||
}
|
||||
|
||||
// ===== 버튼 =====
|
||||
void Apply_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_state.SleepStartMin = _startMin;
|
||||
_state.SleepEndMin = _endMin;
|
||||
_owner.ApplySmartSleep();
|
||||
Close();
|
||||
}
|
||||
|
||||
void Close_Click(object sender, RoutedEventArgs e) => Close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user