History graph now is zoomable and draggable.

Also fixed missing finesse data in old endcontexts
This commit is contained in:
dan63047 2024-01-17 01:55:21 +03:00
parent a6b3a0282a
commit 14def01b57
2 changed files with 85 additions and 51 deletions

View File

@ -548,13 +548,13 @@ class EndContextSingle {
late Duration finalTime;
late int tSpins;
late Clears clears;
late Finesse finesse;
late Finesse? finesse;
double get pps => piecesPlaced / (finalTime.inMicroseconds / 1000000);
double get kpp => inputs / piecesPlaced;
double get spp => score / piecesPlaced;
double get kps => inputs / (finalTime.inMicroseconds / 1000000);
double get finessePercentage => finesse.perfectPieces / piecesPlaced;
double get finessePercentage => finesse != null ? finesse!.perfectPieces / piecesPlaced : 0;
EndContextSingle(
{required this.gameType,
@ -585,7 +585,7 @@ class EndContextSingle {
tSpins = json['tspins'];
piecesPlaced = json['piecesplaced'];
clears = Clears.fromJson(json['clears']);
finesse = Finesse.fromJson(json['finesse']);
finesse = json.containsKey("finesse") ? Finesse.fromJson(json['finesse']) : null;
gameType = json['gametype'];
}
@ -602,7 +602,7 @@ class EndContextSingle {
data['tspins'] = tSpins;
data['piecesplaced'] = piecesPlaced;
data['clears'] = clears.toJson();
data['finesse'] = finesse.toJson();
if (finesse != null) data['finesse'] = finesse!.toJson();
data['finalTime'] = finalTime;
data['gametype'] = gameType;
return data;

View File

@ -312,13 +312,13 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
onRefresh: () {
return Future(() => changePlayer(snapshot.data![0].userId));
},
notificationPredicate: (notification) {
// with NestedScrollView local(depth == 2) OverscrollNotification are not sent
if (!kIsWeb && (notification is OverscrollNotification || Platform.isIOS)) {
return notification.depth == 2;
}
return notification.depth == 0;
},
// notificationPredicate: (notification) {
// // with NestedScrollView local(depth == 2) OverscrollNotification are not sent
// if (!kIsWeb && (notification is OverscrollNotification || Platform.isIOS)) {
// return notification.depth == 2;
// }
// return notification.depth == 0;
// },
child: NestedScrollView(
controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
@ -617,7 +617,9 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
late double minX;
late double maxX;
late double minY;
late double actualMinY;
late double maxY;
late double actualMaxY;
@override
void initState(){
@ -640,11 +642,25 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
return element;
}
}).y;
actualMaxY = maxY;
actualMinY = minY;
}
@override
void dispose(){
super.dispose();
actualMinY = 0;
minY = 0;
}
@override
Widget build(BuildContext context) {
GlobalKey graphKey = GlobalKey();
double xScale = maxX - minX;
double yScale = maxY - minY;
double scaleFactor = 5e2;
double dragFactor = 7e2;
double xInterval = widget.bigScreen ? max(1, xScale / 6) : max(1, xScale / 3);
EdgeInsets padding = widget.bigScreen ? const EdgeInsets.fromLTRB(40, 30, 40, 30) : const EdgeInsets.fromLTRB(0, 40, 16, 48);
double graphStartX = padding.left+widget.leftSpace;
@ -653,35 +669,48 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 104,
child: Listener(
behavior: HitTestBehavior.translucent,
onPointerSignal: (signal) {
if (signal is PointerScrollEvent) {
RenderBox graphBox = graphKey.currentContext?.findRenderObject() as RenderBox;
Offset graphPosition = graphBox.localToGlobal(Offset.zero);
double scrollPosRelativeX = (signal.position.dx - graphStartX) / (graphEndX - graphStartX);
double newMinX, newMaxX;
newMinX = minX - (xScale / 5e2) * signal.scrollDelta.dy * scrollPosRelativeX;
newMaxX = maxX + (xScale / 5e2) * signal.scrollDelta.dy * (1-scrollPosRelativeX);
double scrollPosRelativeY = (signal.position.dy - graphPosition.dy) / (graphBox.size.height - 30); // size - bottom titles height
double newMinX, newMaxX, newMinY, newMaxY;
newMinX = minX - (xScale / scaleFactor) * signal.scrollDelta.dy * scrollPosRelativeX;
newMaxX = maxX + (xScale / scaleFactor) * signal.scrollDelta.dy * (1-scrollPosRelativeX);
newMinY = minY - (yScale / scaleFactor) * signal.scrollDelta.dy * (1-scrollPosRelativeY);
newMaxY = maxY + (yScale / scaleFactor) * signal.scrollDelta.dy * scrollPosRelativeY;
if ((newMaxX - newMinX).isNegative) return;
if ((newMaxY - newMinY).isNegative) return;
setState(() {
minX = max(newMinX, widget.data.first.x);
maxX = min(newMaxX, widget.data.last.x);
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
minY = max(newMinY, actualMinY);
maxY = min(newMaxY, actualMaxY);
_scrollController.jumpTo(_scrollController.position.maxScrollExtent - signal.scrollDelta.dy);
});
}
},
child:
GestureDetector(
behavior: HitTestBehavior.opaque,
onDoubleTap: () {
setState(() {
minX = widget.data.first.x;
maxX = widget.data.last.x;
minY = actualMinY;
maxY = actualMaxY;
});
},
onHorizontalDragUpdate: (dragUpdDet) {
var horizontalDistance = dragUpdDet.primaryDelta ?? 0;
if (horizontalDistance == 0) return;
onPanUpdate: (dragUpdDet) {
print(dragUpdDet);
setState(() {
minX -= (xScale / 7e2) * horizontalDistance;
maxX -= (xScale / 7e2) * horizontalDistance;
minX -= (xScale / dragFactor) * dragUpdDet.delta.dx;
maxX -= (xScale / dragFactor) * dragUpdDet.delta.dx;
minY += (yScale / dragFactor) * dragUpdDet.delta.dy;
maxY += (yScale / dragFactor) * dragUpdDet.delta.dy;
if (minX < widget.data.first.x) {
minX = widget.data.first.x;
@ -693,8 +722,10 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
}
});
},
child: AbsorbPointer(
child: Padding( padding: padding,
child: LineChart(
key: graphKey,
LineChartData(
lineBarsData: [LineChartBarData(spots: widget.data)],
clipData: const FlClipData.all(),
@ -702,6 +733,8 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
gridData: FlGridData(verticalInterval: xInterval),
minX: minX,
maxX: maxX,
minY: minY,
maxY: maxY,
titlesData: FlTitlesData(topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
bottomTitles: AxisTitles(sideTitles: SideTitles(interval: xInterval, showTitles: true, reservedSize: 30, getTitlesWidget: (double value, TitleMeta meta){
@ -723,6 +756,7 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
),
),
),
),
)
);
}
@ -810,12 +844,12 @@ class _RecordThingy extends StatelessWidget {
fractionDigits: 2,
isScreenBig: bigScreen,
higherIsBetter: true,),
StatCellNum(
playerStat: record!.endContext!.finesse.faults,
if (record!.endContext!.finesse != null) StatCellNum(
playerStat: record!.endContext!.finesse!.faults,
playerStatLabel: t.statCellNum.finesseFaults,
isScreenBig: bigScreen,
higherIsBetter: false,),
StatCellNum(
if (record!.endContext!.finesse != null) StatCellNum(
playerStat:
record!.endContext!.finessePercentage * 100,
playerStatLabel: t.statCellNum.finessePercentage,