海报从 Empurple 的 Best50ImageRenderer/ImageBuilder 移植:按原始像素坐标 (1762x1850 画布、300x100 卡片、5 列、行距 120) 叠加在 base.png 上,底图里 已画好的面板/药丸标签/页脚不重复绘制;页面外壳走 Ichino 的 Material 3。 RatingCalculator 的达成率分档改成单张有序表,避免偏移与评级错位; RA 与评级由 test/rating_calculator_test.dart 的边界用例锁定。 GetUserRatingApi 只需要 userId(Cookie 可选),所以 Preview API 模式、未登录 游戏服务器时也能出图,只是没有 FC/AP/FS 标记。导出用 RepaintBoundary 抓 全尺寸 PNG:原生走 share_plus(不支持文件分享的平台回退为落盘并提示路径), web 走下载。 BEST35 与 BEST15 改为各自独立排版。原先沿用 Empurple 的跨列表全局序号, BEST35 没打满时 BEST15 会整体上移混进上半区。 path_provider 会经 path_provider_android 2.3.x 拖入 jni 插件,而 jni 把 windows/linux 也声明成 ffiPlugin,桌面构建因此去链接 jvm.lib 并失败, 故用 dependency_overrides 钉住 path_provider_android <2.3.0。
81 lines
2.1 KiB
Dart
81 lines
2.1 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:ichino/services/rating_calculator.dart';
|
|
|
|
/// achievementRaw 接口原值(百分比 * 10000)。
|
|
double _pct(int raw) => raw / 10000.0;
|
|
|
|
void main() {
|
|
group('评级区间边界', () {
|
|
const cases = <int, String>{
|
|
0: 'D',
|
|
99999: 'D',
|
|
100000: 'D',
|
|
499999: 'D',
|
|
500000: 'C',
|
|
599999: 'C',
|
|
600000: 'B',
|
|
699999: 'B',
|
|
700000: 'BB',
|
|
749999: 'BB',
|
|
750000: 'BBB',
|
|
799999: 'BBB',
|
|
800000: 'A',
|
|
899999: 'A',
|
|
900000: 'AA',
|
|
939999: 'AA',
|
|
940000: 'AAA',
|
|
969999: 'AAA',
|
|
970000: 'S',
|
|
979999: 'S',
|
|
980000: 'Sp',
|
|
989999: 'Sp',
|
|
990000: 'SS',
|
|
994999: 'SS',
|
|
995000: 'SSp',
|
|
999999: 'SSp',
|
|
1000000: 'SSS',
|
|
1004999: 'SSS',
|
|
1005000: 'SSSp',
|
|
};
|
|
|
|
cases.forEach((raw, expected) {
|
|
test('$raw => $expected', () {
|
|
expect(RatingCalculator.compute(10.0, _pct(raw)).rate, expected);
|
|
});
|
|
});
|
|
});
|
|
|
|
group('RA 计算', () {
|
|
test('低于 10% 时 RA 为 0', () {
|
|
expect(RatingCalculator.computeRa(10.0, _pct(99999)), 0);
|
|
});
|
|
|
|
test('ds 10.0 / 100.1234% => 216', () {
|
|
expect(RatingCalculator.compute(10.0, _pct(1001234)).ra, 216);
|
|
});
|
|
|
|
test('ds 10.0 / 99.0000% => 205 (整数截断)', () {
|
|
expect(RatingCalculator.compute(10.0, _pct(990000)).ra, 205);
|
|
});
|
|
|
|
test('ds 10.0 / 100.5% 封顶 SSSp => 225', () {
|
|
expect(RatingCalculator.compute(10.0, _pct(1005000)).ra, 225);
|
|
});
|
|
|
|
test('超出 100.5% 的达成率被夹到上限', () {
|
|
final clamped = RatingCalculator.compute(10.0, _pct(1200000));
|
|
final capped = RatingCalculator.compute(10.0, _pct(1005000));
|
|
expect(clamped.ra, capped.ra);
|
|
expect(clamped.rate, capped.rate);
|
|
});
|
|
|
|
test('定数 13.0 / 100% => 280', () {
|
|
expect(RatingCalculator.compute(13.0, _pct(1000000)).ra, 280);
|
|
});
|
|
|
|
test('缺失定数 (ds=0) 时 RA 为 0', () {
|
|
expect(RatingCalculator.computeRa(0.0, _pct(1005000)), 0);
|
|
});
|
|
});
|
|
}
|