Skip to content

Commit

Permalink
Added initial logic to the tierlist builder
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Feb 8, 2021
1 parent 2f7c515 commit 5881f61
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/application/bloc.dart
Expand Up @@ -10,6 +10,7 @@ export 'main/main_bloc.dart';
export 'main_tab/main_tab_bloc.dart';
export 'materials/materials_bloc.dart';
export 'settings/settings_bloc.dart';
export 'tierlist/tier_list_bloc.dart';
export 'url_page/url_page_bloc.dart';
export 'weapon/weapon_bloc.dart';
export 'weapons/weapons_bloc.dart';
153 changes: 153 additions & 0 deletions lib/application/tierlist/tier_list_bloc.dart
@@ -0,0 +1,153 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:genshindb/domain/models/models.dart';
import 'package:genshindb/domain/services/genshin_service.dart';
import 'package:genshindb/domain/services/telemetry_service.dart';
import 'package:meta/meta.dart';

part 'tier_list_bloc.freezed.dart';
part 'tier_list_event.dart';
part 'tier_list_state.dart';

class TierListBloc extends Bloc<TierListEvent, TierListState> {
final GenshinService _genshinService;
final TelemetryService _telemetryService;
final List<int> defaultColors = [
0xfff44336,
0xffff9800,
0xffffc107,
0xffffeb3b,
0xff8bc34a,
];

_LoadedState get currentState => state as _LoadedState;

TierListBloc(this._genshinService, this._telemetryService) : super(const TierListState.loading());

@override
Stream<TierListState> mapEventToState(TierListEvent event) async* {
if (event is _Init) {
yield const TierListState.loading();
}

final s = await event.map(
init: (_) async => _init(),
rowTextChanged: (e) async => _rowTextChanged(e.index, e.newValue),
rowPositionChanged: (e) async => _rowPositionChanged(e.index, e.newIndex),
rowColorChanged: (e) async => _rowColorChanged(e.index, e.newColor),
addNewRow: (e) async => _addNewRow(e.index, e.above),
deleteRow: (e) async => _deleteRow(e.index),
clearRow: (e) async => _clearRow(e.index),
clearAllRows: (_) async => _clearAllRows(),
addCharacterToRow: (e) async => _addCharacterToRow(e.index, e.charImg),
deleteCharacterFromRow: (e) async => _deleteCharacterFromRow(e.index, e.charImg),
readyToSave: (e) async => currentState.copyWith.call(readyToSave: e.ready),
);

yield s;
}

Future<TierListState> _init() async {
await _telemetryService.trackTierListOpened();
final defaultTierList = _genshinService.getDefaultCharacterTierList(defaultColors);
return TierListState.loaded(rows: defaultTierList, charsAvailable: [], readyToSave: false);
}

TierListState _rowTextChanged(int index, String newValue) {
final updated = currentState.rows.elementAt(index).copyWith.call(tierText: newValue);
final rows = _updateRows(updated, index, index);
return currentState.copyWith.call(rows: rows);
}

TierListState _rowPositionChanged(int index, int newIndex) {
final updated = currentState.rows.elementAt(index);
final rows = _updateRows(updated, newIndex, index);
return currentState.copyWith.call(rows: rows);
}

TierListState _rowColorChanged(int index, int newColor) {
final updated = currentState.rows.elementAt(index).copyWith.call(tierColor: newColor);
final rows = _updateRows(updated, index, index);
return currentState.copyWith.call(rows: rows);
}

TierListState _addNewRow(int index, bool above) {
final colorsCopy = [...defaultColors];
final color = (colorsCopy..shuffle()).first;
final newIndex = above ? index : index + 1;

final newRow = TierListRowModel.row(tierText: (currentState.rows.length + 1).toString(), tierColor: color, charImgs: []);
final rows = [...currentState.rows];
rows.insert(newIndex, newRow);
return currentState.copyWith.call(rows: rows);
}

TierListState _deleteRow(int index) {
if (currentState.rows.length == 1) {
return currentState;
}
final rows = [...currentState.rows];
final row = rows.elementAt(index);
final chars = _updateAvailableChars([...currentState.charsAvailable, ...row.charImgs], []);
rows.removeAt(index);
return currentState.copyWith.call(rows: rows, charsAvailable: chars);
}

TierListState _clearRow(int index) {
final row = currentState.rows.elementAt(index);
final updated = row.copyWith.call(charImgs: []);
final rows = _updateRows(updated, index, index);
final chars = _updateAvailableChars([...currentState.charsAvailable, ...row.charImgs], []);
return currentState.copyWith.call(rows: rows, charsAvailable: chars);
}

TierListState _clearAllRows() {
final chars = _updateAvailableChars(_genshinService.getDefaultCharacterTierList(defaultColors).expand((row) => row.charImgs).toList(), []);
final updatedRows = currentState.rows.map((row) => row.copyWith.call(charImgs: [])).toList();
return currentState.copyWith.call(rows: updatedRows, charsAvailable: chars, readyToSave: false);
}

TierListState _addCharacterToRow(int index, String charImg) {
final row = currentState.rows.elementAt(index);
final updated = row.copyWith.call(charImgs: [...row.charImgs, charImg]);
final updatedChars = _updateAvailableChars(currentState.charsAvailable, [charImg]);
return currentState.copyWith.call(rows: _updateRows(updated, index, index), charsAvailable: updatedChars);
}

TierListState _deleteCharacterFromRow(int index, String charImg) {
final row = currentState.rows.elementAt(index);
final updated = row.copyWith.call(charImgs: row.charImgs.where((img) => img != charImg).toList());
final updatedChars = _updateAvailableChars([...currentState.charsAvailable, charImg], []);
return currentState.copyWith.call(rows: _updateRows(updated, index, index), charsAvailable: updatedChars, readyToSave: false);
}

List<TierListRowModel> _updateRows(TierListRowModel updated, int newIndex, int excludeIndex) {
final rows = <TierListRowModel>[];

if (newIndex < 0 || newIndex == currentState.rows.length) {
return currentState.rows;
}

for (int i = 0; i < currentState.rows.length; i++) {
if (i == excludeIndex) {
continue;
}
final row = currentState.rows[i];
rows.add(row);
}

rows.insert(newIndex, updated);
// rows.sort((x, y) => x.index - y.index);
return rows;
}

List<String> _updateAvailableChars(List<String> from, List<String> exclude) {
var chars = from;
if (exclude.isNotEmpty) {
chars = chars.where((img) => !exclude.contains(img)).toList();
}
return chars..sort((x, y) => x.compareTo(y));
}
}
48 changes: 48 additions & 0 deletions lib/application/tierlist/tier_list_event.dart
@@ -0,0 +1,48 @@
part of 'tier_list_bloc.dart';

@freezed
abstract class TierListEvent with _$TierListEvent {
const factory TierListEvent.init() = _Init;

const factory TierListEvent.rowTextChanged({
@required int index,
@required String newValue,
}) = _RowTextChanged;

const factory TierListEvent.rowPositionChanged({
@required int index,
@required int newIndex,
}) = _RowPositionChanged;

const factory TierListEvent.rowColorChanged({
@required int index,
@required int newColor,
}) = _RowColorChanged;

const factory TierListEvent.addNewRow({
@required int index,
@required bool above,
}) = _AddRow;

const factory TierListEvent.deleteRow({
@required int index,
}) = _DeleteRow;

const factory TierListEvent.clearRow({
@required int index,
}) = _ClearRow;

const factory TierListEvent.clearAllRows() = _ClearAllRows;

const factory TierListEvent.addCharacterToRow({
@required int index,
@required String charImg,
}) = _AddCharacterToRow;

const factory TierListEvent.deleteCharacterFromRow({
@required int index,
@required String charImg,
}) = _DeleteCharacterFromRow;

const factory TierListEvent.readyToSave({@required bool ready}) = _ReadyToSave;
}
12 changes: 12 additions & 0 deletions lib/application/tierlist/tier_list_state.dart
@@ -0,0 +1,12 @@
part of 'tier_list_bloc.dart';

@freezed
abstract class TierListState with _$TierListState {
const factory TierListState.loading() = _LoadingState;

const factory TierListState.loaded({
@required List<TierListRowModel> rows,
@required List<String> charsAvailable,
@required bool readyToSave,
}) = _LoadedState;
}
1 change: 1 addition & 0 deletions lib/domain/models/db/characters/character_file_model.dart
Expand Up @@ -29,6 +29,7 @@ abstract class CharacterFileModel implements _$CharacterFileModel {
@required bool isComingSoon,
@required bool isNew,
@required CharacterType role,
@required String tier,
String birthday,
@required List<CharacterFileAscensionMaterialModel> ascensionMaterials,
@required List<CharacterFileTalentAscensionMaterialModel> talentAscensionMaterials,
Expand Down
1 change: 1 addition & 0 deletions lib/domain/models/models.dart
Expand Up @@ -33,5 +33,6 @@ export 'home/today_weapon_ascension_material_model.dart';
export 'items/item_ascension_material_model.dart';
export 'language_model.dart';
export 'settings/app_settings.dart';
export 'tierlist/tierlist_row_model.dart';
export 'weapons/weapon_card_model.dart';
export 'weapons/weapon_file_refinement_model.dart';
12 changes: 12 additions & 0 deletions lib/domain/models/tierlist/tierlist_row_model.dart
@@ -0,0 +1,12 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'tierlist_row_model.freezed.dart';

@freezed
abstract class TierListRowModel with _$TierListRowModel {
factory TierListRowModel.row({
String tierText,
int tierColor,
List<String> charImgs,
}) = _Row;
}
1 change: 1 addition & 0 deletions lib/domain/services/genshin_service.dart
Expand Up @@ -14,6 +14,7 @@ abstract class GenshinService {
CharacterFileModel getCharacter(String key);
CharacterFileModel getCharacterByImg(String img);
List<CharacterFileModel> getCharactersForBirthday(DateTime date);
List<TierListRowModel> getDefaultCharacterTierList(List<int> colors);

List<WeaponCardModel> getWeaponsForCard();
WeaponCardModel getWeaponForCardByImg(String image);
Expand Down
2 changes: 2 additions & 0 deletions lib/domain/services/telemetry_service.dart
Expand Up @@ -23,4 +23,6 @@ abstract class TelemetryService {
Future<void> trackUrlOpened(bool loadMap, bool loadWishSimulator, bool networkAvailable);

Future<void> trackCalculatorItemAscMaterialLoaded(String item);

Future<void> trackTierListOpened();
}
34 changes: 34 additions & 0 deletions lib/infrastructure/genshin_service.dart
Expand Up @@ -130,6 +130,40 @@ class GenshinServiceImpl implements GenshinService {
}).toList();
}

@override
List<TierListRowModel> getDefaultCharacterTierList(List<int> colors) {
assert(colors.length == 5);

final sTier = _charactersFile.characters
.where((char) => !char.isComingSoon && char.tier == 's')
.map((char) => Assets.getCharacterPath(char.image))
.toList();
final aTier = _charactersFile.characters
.where((char) => !char.isComingSoon && char.tier == 'a')
.map((char) => Assets.getCharacterPath(char.image))
.toList();
final bTier = _charactersFile.characters
.where((char) => !char.isComingSoon && char.tier == 'b')
.map((char) => Assets.getCharacterPath(char.image))
.toList();
final cTier = _charactersFile.characters
.where((char) => !char.isComingSoon && char.tier == 'c')
.map((char) => Assets.getCharacterPath(char.image))
.toList();
final dTier = _charactersFile.characters
.where((char) => !char.isComingSoon && char.tier == 'd')
.map((char) => Assets.getCharacterPath(char.image))
.toList();

return <TierListRowModel>[
TierListRowModel.row(tierText: 'S', tierColor: colors.first, charImgs: sTier),
TierListRowModel.row(tierText: 'A', tierColor: colors[1], charImgs: aTier),
TierListRowModel.row(tierText: 'B', tierColor: colors[2], charImgs: bTier),
TierListRowModel.row(tierText: 'C', tierColor: colors[3], charImgs: cTier),
TierListRowModel.row(tierText: 'D', tierColor: colors.last, charImgs: dTier),
];
}

@override
List<WeaponCardModel> getWeaponsForCard() {
return _weaponsFile.weapons.map(
Expand Down
5 changes: 5 additions & 0 deletions lib/infrastructure/telemetry/telemetry_service.dart
Expand Up @@ -70,4 +70,9 @@ class TelemetryServiceImpl implements TelemetryService {
'Name': item,
});
}

@override
Future<void> trackTierListOpened() async {
await trackEventAsync('TierList-Opened');
}
}

0 comments on commit 5881f61

Please sign in to comment.