Experimenting with layout

This commit is contained in:
dan63047 2024-03-14 01:44:53 +03:00
parent a726357f69
commit 8b95a32007
4 changed files with 109 additions and 11 deletions

View File

@ -38,6 +38,25 @@ const Map<String, double> rankCutoffs = {
"z": -1,
"": 0.5
};
const Map<String, double> rankTargets = {
"x": 24008,
"u": 23038,
"ss": 21583,
"s+": 20128,
"s": 18673,
"s-": 16975,
"a+": 15035,
"a": 13095,
"a-": 11155,
"b+": 9215,
"b": 7275,
"b-": 5335,
"c+": 3880,
"c": 2425,
"c-": 1213,
"d+": 606,
"d": 0,
};
enum Stats {
tr,
glicko,
@ -1883,6 +1902,26 @@ class TetrioPlayersLeaderboard {
'z': getAverageOfRank("z")
};
Map<String, double> get cutoffs => {
'x': getAverageOfRank("x")[1]["toEnterTR"],
'u': getAverageOfRank("u")[1]["toEnterTR"],
'ss': getAverageOfRank("ss")[1]["toEnterTR"],
's+': getAverageOfRank("s+")[1]["toEnterTR"],
's': getAverageOfRank("s")[1]["toEnterTR"],
's-': getAverageOfRank("s-")[1]["toEnterTR"],
'a+': getAverageOfRank("a+")[1]["toEnterTR"],
'a': getAverageOfRank("a")[1]["toEnterTR"],
'a-': getAverageOfRank("a-")[1]["toEnterTR"],
'b+': getAverageOfRank("b+")[1]["toEnterTR"],
'b': getAverageOfRank("b")[1]["toEnterTR"],
'b-': getAverageOfRank("b-")[1]["toEnterTR"],
'c+': getAverageOfRank("c+")[1]["toEnterTR"],
'c': getAverageOfRank("c")[1]["toEnterTR"],
'c-': getAverageOfRank("c-")[1]["toEnterTR"],
'd+': getAverageOfRank("d+")[1]["toEnterTR"],
'd': getAverageOfRank("d")[1]["toEnterTR"]
};
TetrioPlayersLeaderboard.fromJson(List<dynamic> json, String t, DateTime ts) {
type = t;
timestamp = ts;

View File

@ -728,6 +728,14 @@ class TetrioService extends DB {
return matches;
}
/// Gets and returns an amount of stored Tetra League mathes between [ourPlayerID] and [enemyPlayerID].
Future<int> getNumberOfTLMatchesBetweenPlayers(String ourPlayerID, String enemyPlayerID) async {
await ensureDbIsOpen();
final db = getDatabaseOrThrow();
final results = await db.rawQuery("SELECT COUNT(*) from tetrioAlphaLeagueMathces WHERE (player1id = $ourPlayerID AND player2id = $enemyPlayerID) OR (player1id = $enemyPlayerID AND player2id = $ourPlayerID)");
return results.first.values.first as int;
}
/// Deletes match and stats of that match with given [matchID] from local DB. Throws an exception if fails.
Future<void> deleteTLMatch(String matchID) async {
await ensureDbIsOpen();

View File

@ -88,6 +88,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
final bodyGlobalKey = GlobalKey();
bool _showSearchBar = false;
late TabController _tabController;
late TabController _wideScreenTabController;
late bool fixedScroll;
@override
@ -95,6 +96,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
initDB();
_scrollController = ScrollController();
_tabController = TabController(length: 6, vsync: this);
_wideScreenTabController = TabController(length: 4, vsync: this);
// We need to show something
if (widget.player != null){ // if we have user input,
@ -279,12 +281,12 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
final t = Translations.of(context);
bool bigScreen = MediaQuery.of(context).size.width > 768;
bool bigScreen = MediaQuery.of(context).size.width > 1024;
return Scaffold(
drawer: widget.player == null ? NavDrawer(changePlayer) : null, // Side menu hidden if player provided
drawerEdgeDragWidth: MediaQuery.of(context).size.width * 0.2, // 20% of left side of the screen used of Drawer gesture
appBar: AppBar(
title: _showSearchBar ? SearchBox(onSubmit: changePlayer, bigScreen: bigScreen) : Text(widget.title, style: const TextStyle(shadows: textShadow)),
title: _showSearchBar ? SearchBox(onSubmit: changePlayer, bigScreen: MediaQuery.of(context).size.width > 768) : Text(widget.title, style: const TextStyle(shadows: textShadow)),
backgroundColor: Colors.black,
actions: widget.player == null ? [ // search bar and PopupMenuButton hidden if player provided TODO: Subject to change
_showSearchBar
@ -374,8 +376,9 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
return notification.depth == 0;
},
child: NestedScrollView(
controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
controller: _scrollController,
scrollBehavior: const MaterialScrollBehavior(),
headerSliverBuilder: (context, value) {
return [
SliverToBoxAdapter(
@ -386,10 +389,15 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
)),
SliverToBoxAdapter(
child: TabBar(
controller: _tabController,
controller: bigScreen ? _wideScreenTabController : _tabController,
padding: const EdgeInsets.all(0.0),
isScrollable: true,
tabs: [
tabs: bigScreen ? [
Tab(text: t.tetraLeague,),
Tab(text: t.history),
Tab(text: "${t.sprint} & ${t.blitz}"),
Tab(text: t.other),
] : [
Tab(text: t.tetraLeague),
Tab(text: t.tlRecords),
Tab(text: t.history),
@ -402,8 +410,44 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
];
},
body: TabBarView(
controller: _tabController,
controller: bigScreen ? _wideScreenTabController : _tabController,
children: bigScreen ? [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width-450,
constraints: BoxConstraints(maxWidth: 1024),
child: TLThingy(
tl: snapshot.data![0].tlSeason1,
userID: snapshot.data![0].userId,
states: snapshot.data![2],
topTR: snapshot.data![7],
bot: snapshot.data![0].role == "bot",
guest: snapshot.data![0].role == "anon",
lbPositions: meAmongEveryone
),
),
SizedBox(
width: 450,
child: _TLRecords(userID: snapshot.data![0].userId, data: snapshot.data![3])
),
],),
_History(states: snapshot.data![2], update: _justUpdate),
Row(children: [
Container(
width: MediaQuery.of(context).size.width/2,
padding: EdgeInsets.only(right: 8),
child: _RecordThingy(record: snapshot.data![1]['sprint'], rank: snapshot.data![0].tlSeason1.percentileRank)
),
Container(
width: MediaQuery.of(context).size.width/2,
padding: EdgeInsets.only(left: 8),
child: _RecordThingy(record: snapshot.data![1]['blitz'], rank: snapshot.data![0].tlSeason1.percentileRank)
),
],),
_OtherThingy(zen: snapshot.data![1]['zen'], bio: snapshot.data![0].bio, distinguishment: snapshot.data![0].distinguishment, newsletter: snapshot.data![6],)
] : [
TLThingy(
tl: snapshot.data![0].tlSeason1,
userID: snapshot.data![0].userId,
@ -600,9 +644,10 @@ class _TLRecords extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (data.isEmpty) return Center(child: Text(t.noRecords, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)));
bool bigScreen = MediaQuery.of(context).size.width > 768;
bool bigScreen = MediaQuery.of(context).size.width >= 768;
return ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
controller: ScrollController(),
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
var accentColor = data[index].endContext.firstWhere((element) => element.userId == userID).success ? Colors.green : Colors.red;

View File

@ -27,7 +27,11 @@ class TLThingy extends StatefulWidget {
final double? topTR;
final PlayerLeaderboardPosition? lbPositions;
final TetraLeagueAlpha? averages;
const TLThingy({super.key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.guest=false, this.topTR, this.lbPositions, this.averages});
final double? thatRankCutoff;
final double? thatRankTarget;
final double? nextRankCutoff;
final double? nextRankTarget;
const TLThingy({super.key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.guest=false, this.topTR, this.lbPositions, this.averages, this.nextRankCutoff = 25000, this.thatRankCutoff = 0, this.nextRankTarget = 25000, this.thatRankTarget = 0});
@override
State<TLThingy> createState() => _TLThingyState();
@ -55,7 +59,7 @@ class _TLThingyState extends State<TLThingy> {
NumberFormat fractionfEstTRAcc = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3)..maximumIntegerDigits = 0;
if (currentTl.gamesPlayed == 0) return Center(child: Text(widget.guest ? t.anonTL : widget.bot ? t.botTL : t.neverPlayedTL, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28), textAlign: TextAlign.center,));
return LayoutBuilder(builder: (context, constraints) {
bool bigScreen = constraints.maxWidth > 768;
bool bigScreen = constraints.maxWidth >= 768;
return ListView.builder(
physics: const ClampingScrollPhysics(),
itemCount: 1,
@ -313,7 +317,9 @@ class _TLThingyState extends State<TLThingy> {
color: oldTl!.estTr!.esttr > currentTl.estTr!.esttr ? Colors.redAccent : Colors.greenAccent
),),
if (oldTl?.estTr?.esttr != null && widget.lbPositions?.estTr != null) const TextSpan(text: ""),
if (widget.lbPositions?.estTr != null) TextSpan(text: widget.lbPositions!.estTr!.position >= 1000 ? "Top ${f2.format(widget.lbPositions!.estTr!.percentage*100)}%" : "${widget.lbPositions!.estTr!.position}")
if (widget.lbPositions?.estTr != null) TextSpan(text: widget.lbPositions!.estTr!.position >= 1000 ? "Top ${f2.format(widget.lbPositions!.estTr!.percentage*100)}%" : "${widget.lbPositions!.estTr!.position}"),
if (widget.lbPositions?.estTr != null) const TextSpan(text: ""),
TextSpan(text: "Glicko: ${f2.format(currentTl.estTr!.estglicko)}")
]
),
),