Skip to content

Commit

Permalink
This now allows us to show the required exp. materials in the calculator
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Mar 7, 2021
1 parent 4160c8d commit 28a0654
Show file tree
Hide file tree
Showing 18 changed files with 345 additions and 131 deletions.
Expand Up @@ -42,16 +42,16 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
image: Assets.getCharacterPath(char.image),
name: translation.name,
rarity: char.rarity,
materials: _getCharacterMaterialsToUse(char, e.currentAscensionLevel, e.desiredAscensionLevel, e.skills),
materials: _getCharacterMaterialsToUse(char, e.currentLevel, e.desiredLevel, e.currentAscensionLevel, e.desiredAscensionLevel, e.skills),
currentLevel: e.currentLevel,
desiredLevel: e.desiredLevel,
skills: e.skills,
desiredAscensionLevel: e.desiredAscensionLevel,
currentAscensionLevel: e.currentAscensionLevel,
)
];

return currentState.copyWith.call(items: items, summary: _generateSummary(items.expand((i) => i.materials).toList()));
final materialsForSummary = _buildMaterialsForSummary(items);
return currentState.copyWith.call(items: items, summary: _generateSummary(materialsForSummary));
},
addWeapon: (e) async {
await _telemetryService.trackCalculatorItemAscMaterialLoaded(e.key);
Expand All @@ -64,30 +64,33 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
image: weapon.fullImagePath,
name: translation.name,
rarity: weapon.rarity,
materials: _getWeaponMaterialsToUse(weapon, e.currentAscensionLevel, e.desiredAscensionLevel),
materials: _getWeaponMaterialsToUse(weapon, e.currentLevel, e.desiredLevel, e.currentAscensionLevel, e.desiredAscensionLevel),
currentLevel: e.currentLevel,
desiredLevel: e.desiredLevel,
desiredAscensionLevel: e.desiredAscensionLevel,
currentAscensionLevel: e.currentAscensionLevel,
)
];
return currentState.copyWith.call(items: items, summary: _generateSummary(items.expand((i) => i.materials).toList()));
final materialsForSummary = _buildMaterialsForSummary(items);
return currentState.copyWith.call(items: items, summary: _generateSummary(materialsForSummary));
},
removeItem: (e) async {
final items = [...currentState.items];
items.removeAt(e.index);
return currentState.copyWith.call(items: items, summary: _generateSummary(items.expand((i) => i.materials).toList()));
final materialsForSummary = _buildMaterialsForSummary(items);
return currentState.copyWith.call(items: items, summary: _generateSummary(materialsForSummary));
},
updateCharacter: (e) async {
final currentChar = currentState.items.elementAt(e.index);
final char = _genshinService.getCharacter(currentChar.key);
final updatedChar = currentChar.copyWith.call(
materials: _getCharacterMaterialsToUse(char, e.currentAscensionLevel, e.desiredAscensionLevel, e.skills),
materials: _getCharacterMaterialsToUse(char, e.currentLevel, e.desiredLevel, e.currentAscensionLevel, e.desiredAscensionLevel, e.skills),
currentLevel: e.currentLevel,
desiredLevel: e.desiredLevel,
skills: e.skills,
desiredAscensionLevel: e.desiredAscensionLevel,
currentAscensionLevel: e.currentAscensionLevel,
isActive: e.isActive,
);

return _updateItem(e.index, updatedChar);
Expand All @@ -96,11 +99,12 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
final currentWeapon = currentState.items.elementAt(e.index);
final weapon = _genshinService.getWeapon(currentWeapon.key);
final updatedWeapon = currentWeapon.copyWith.call(
materials: _getWeaponMaterialsToUse(weapon, e.currentAscensionLevel, e.desiredAscensionLevel),
materials: _getWeaponMaterialsToUse(weapon, e.currentLevel, e.desiredLevel, e.currentAscensionLevel, e.desiredAscensionLevel),
currentLevel: e.currentLevel,
desiredLevel: e.desiredLevel,
desiredAscensionLevel: e.desiredAscensionLevel,
currentAscensionLevel: e.currentAscensionLevel,
isActive: e.isActive,
);

return _updateItem(e.index, updatedWeapon);
Expand Down Expand Up @@ -164,6 +168,10 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
case MaterialType.ingredient:
key = AscensionMaterialSummaryType.others;
break;
case MaterialType.expWeapon:
case MaterialType.expCharacter:
key = AscensionMaterialSummaryType.exp;
break;
}
newValue = MaterialSummary.others(
key: material.key,
Expand All @@ -187,10 +195,14 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu

List<ItemAscensionMaterialModel> _getCharacterMaterialsToUse(
CharacterFileModel char,
int currentLevel,
int desiredLevel,
int currentAscensionLevel,
int desiredAscensionLevel,
List<CharacterSkill> skills,
) {
final expMaterials = _getItemExperienceMaterials(currentLevel, desiredLevel, true);

final ascensionMaterials =
char.ascensionMaterials.where((m) => m.rank > currentAscensionLevel && m.rank <= desiredAscensionLevel).expand((e) => e.materials).toList();

Expand Down Expand Up @@ -223,20 +235,23 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
}
}

return _flatMaterialsList(ascensionMaterials + skillMaterials);
return _flatMaterialsList(expMaterials + ascensionMaterials + skillMaterials);
}

List<ItemAscensionMaterialModel> _getWeaponMaterialsToUse(
WeaponFileModel weapon,
int currentLevel,
int desiredLevel,
int currentAscensionLevel,
int desiredAscensionLevel,
) {
final expMaterials = _getItemExperienceMaterials(currentLevel, desiredLevel, false);
final materials = weapon.ascensionMaterials
.where((m) => m.level > _mapToWeaponLevel(currentAscensionLevel) && m.level <= _mapToWeaponLevel(desiredAscensionLevel))
.expand((m) => m.materials)
.toList();

return _flatMaterialsList(materials);
return _flatMaterialsList(expMaterials + materials);
}

List<ItemAscensionMaterialModel> _flatMaterialsList(List<ItemAscensionMaterialModel> current) {
Expand All @@ -255,7 +270,12 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
final items = [...currentState.items];
items.removeAt(index);
items.insert(index, updatedItem);
return currentState.copyWith.call(items: items, summary: _generateSummary(items.expand((i) => i.materials).toList()));
final materialsForSummary = _buildMaterialsForSummary(items);
return currentState.copyWith.call(items: items, summary: _generateSummary(materialsForSummary));
}

List<ItemAscensionMaterialModel> _buildMaterialsForSummary(List<ItemAscensionMaterials> items) {
return items.where((i) => i.isActive).expand((i) => i.materials).toList();
}

int _mapToWeaponLevel(int val) {
Expand All @@ -269,4 +289,32 @@ class CalculatorAscMaterialsBloc extends Bloc<CalculatorAscMaterialsEvent, Calcu
return entry.value;
}
}

List<ItemAscensionMaterialModel> _getItemExperienceMaterials(int currentLevel, int desiredLevel, bool forCharacters) {
final materials = <ItemAscensionMaterialModel>[];
//Here we order the exp materials in a way that the one that gives more exp is first and so on
final expMaterials = _genshinService.getMaterials(forCharacters ? MaterialType.expCharacter : MaterialType.expWeapon)
..sort((x, y) => (y.experienceAttributes.experience - x.experienceAttributes.experience).round());
var requiredExp = getItemTotalExp(currentLevel, desiredLevel, forCharacters);
final moraMaterial = _genshinService.getMaterials(MaterialType.currency).first;

for (final material in expMaterials) {
if (requiredExp <= 0) {
break;
}

final matExp = material.experienceAttributes.experience;
final quantity = (requiredExp / matExp).floor();
if (quantity == 0) {
continue;
}
materials.add(ItemAscensionMaterialModel(quantity: quantity, image: material.image, materialType: material.type));
requiredExp -= quantity * matExp;

final requiredMora = quantity * material.experienceAttributes.pricePerUsage;
materials.add(ItemAscensionMaterialModel(quantity: requiredMora.round(), image: moraMaterial.image, materialType: moraMaterial.type));
}

return materials.reversed.toList();
}
}
Expand Up @@ -20,6 +20,7 @@ abstract class CalculatorAscMaterialsEvent with _$CalculatorAscMaterialsEvent {
@required int currentAscensionLevel,
@required int desiredAscensionLevel,
@required List<CharacterSkill> skills,
@required bool isActive,
}) = _UpdateCharacter;

const factory CalculatorAscMaterialsEvent.addWeapon({
Expand All @@ -36,6 +37,7 @@ abstract class CalculatorAscMaterialsEvent with _$CalculatorAscMaterialsEvent {
@required int desiredLevel,
@required int currentAscensionLevel,
@required int desiredAscensionLevel,
@required bool isActive,
}) = _UpdateWeapon;

const factory CalculatorAscMaterialsEvent.removeItem({
Expand Down
Expand Up @@ -19,6 +19,7 @@ abstract class ItemAscensionMaterials with _$ItemAscensionMaterials {
@required int desiredAscensionLevel,
@required List<CharacterSkill> skills,
@Default(true) bool isCharacter,
@Default(true) bool isActive,
}) = _ForCharacter;

const factory ItemAscensionMaterials.forWeapons({
Expand All @@ -34,5 +35,6 @@ abstract class ItemAscensionMaterials with _$ItemAscensionMaterials {
//This are here just for convenience
@Default([]) List<CharacterSkill> skills,
@Default(false) bool isCharacter,
@Default(true) bool isActive,
}) = _ForWeapon;
}
23 changes: 22 additions & 1 deletion lib/domain/models/db/materials/material_file_model.dart
Expand Up @@ -11,17 +11,38 @@ abstract class MaterialFileModel implements _$MaterialFileModel {
@late
String get fullImagePath => Assets.getMaterialPath(image, type);

@late
bool get isAnExperienceMaterial => type == MaterialType.expWeapon || type == MaterialType.expCharacter;

@late
ExperienceMaterialAttributesModel get experienceAttributes =>
isAnExperienceMaterial ? ExperienceMaterialAttributesModel.fromJson(attributes) : null;

factory MaterialFileModel({
@required String key,
@required String image,
@required bool isFromBoss,
@required bool isForCharacters,
@required bool isForWeapons,
@required MaterialType type,
@required List<int> days,
@required int level,
@required double level,
Map<String, dynamic> attributes,
}) = _MaterialFileModel;

MaterialFileModel._();

factory MaterialFileModel.fromJson(Map<String, dynamic> json) => _$MaterialFileModelFromJson(json);
}

@freezed
abstract class ExperienceMaterialAttributesModel implements _$ExperienceMaterialAttributesModel {
factory ExperienceMaterialAttributesModel({
@required double experience,
@required double pricePerUsage,
}) = _ExperienceMaterialAttributesModel;

ExperienceMaterialAttributesModel._();

factory ExperienceMaterialAttributesModel.fromJson(Map<String, dynamic> json) => _$ExperienceMaterialAttributesModelFromJson(json);
}
4 changes: 2 additions & 2 deletions lib/domain/models/db/materials/materials_file.dart
Expand Up @@ -3,13 +3,12 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'material_file_model.dart';

part 'materials_file.freezed.dart';

part 'materials_file.g.dart';

@freezed
abstract class MaterialsFile implements _$MaterialsFile {
@late
List<MaterialFileModel> get materials => talents + weapon + weaponPrimary + common + currency + elemental + jewels + locals;
List<MaterialFileModel> get materials => talents + weapon + weaponPrimary + common + currency + elemental + jewels + locals + experience;

factory MaterialsFile({
@required List<MaterialFileModel> talents,
Expand All @@ -20,6 +19,7 @@ abstract class MaterialsFile implements _$MaterialsFile {
@required List<MaterialFileModel> elemental,
@required List<MaterialFileModel> jewels,
@required List<MaterialFileModel> locals,
@required List<MaterialFileModel> experience,
}) = _MaterialsFile;

MaterialsFile._();
Expand Down
@@ -1,18 +1,18 @@
class ItemExperience {
class ItemExperienceModel {
final int level;
final int nextLevelExp;
final int totalExp;
final double nextLevelExp;
final double totalExp;
final bool isForCharacter;

bool get maxReached => level == -1;

const ItemExperience.forCharacters(
const ItemExperienceModel.forCharacters(
this.level,
this.nextLevelExp,
this.totalExp,
) : isForCharacter = true;

const ItemExperience.forWeapons(
const ItemExperienceModel.forWeapons(
this.level,
this.nextLevelExp,
this.totalExp,
Expand Down
2 changes: 1 addition & 1 deletion lib/domain/models/models.dart
Expand Up @@ -31,7 +31,7 @@ export 'elements/element_reaction_card_model.dart';
export 'home/today_char_ascension_materials_model.dart';
export 'home/today_weapon_ascension_material_model.dart';
export 'items/item_ascension_material_model.dart';
export 'items/item_experience.dart';
export 'items/item_experience_model.dart';
export 'language_model.dart';
export 'settings/app_settings.dart';
export 'tierlist/tierlist_row_model.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/domain/services/genshin_service.dart
Expand Up @@ -39,6 +39,7 @@ abstract class GenshinService {
List<ElementReactionCardModel> getElementResonances();

MaterialFileModel getMaterialByImage(String image);
List<MaterialFileModel> getMaterials(MaterialType type);

int getServerDay(AppServerResetTimeType type);
}
40 changes: 40 additions & 0 deletions lib/domain/utils/currency_utils.dart
@@ -0,0 +1,40 @@
import 'package:intl/intl.dart';

class CurrencyUtils {
static String formatNumber(
int amount, {
int decimalDigits = 0,
bool symbolToTheRight = true,
String thousandSeparator = '.',
String decimalSeparator = ',',
}) {
return _refineSeparator(
amount,
decimalDigits,
thousandSeparator,
decimalSeparator,
);
}

static String _baseFormat(
int amount,
int decimalDigits,
) =>
NumberFormat.currency(
symbol: '',
decimalDigits: decimalDigits,
locale: 'en_US',
).format(amount);

static String _refineSeparator(
int amount,
int decimalDigits,
String thousandSeparator,
String decimalSeparator,
) =>
_baseFormat(amount, decimalDigits)
.replaceAll(',', '(,)')
.replaceAll('.', '(.)')
.replaceAll('(,)', thousandSeparator)
.replaceAll('(.)', decimalSeparator);
}
5 changes: 5 additions & 0 deletions lib/infrastructure/genshin_service.dart
Expand Up @@ -443,6 +443,11 @@ class GenshinServiceImpl implements GenshinService {
return _materialsFile.materials.firstWhere((m) => m.fullImagePath == image);
}

@override
List<MaterialFileModel> getMaterials(MaterialType type) {
return _materialsFile.materials.where((m) => m.type == type).toList();
}

@override
int getServerDay(AppServerResetTimeType type) {
final now = DateTime.now();
Expand Down

0 comments on commit 28a0654

Please sign in to comment.