new classes wip + parsing

This commit is contained in:
Chen Asraf
2022-02-14 01:55:13 +02:00
parent fd9772905a
commit 7c1be49dde
22 changed files with 1198 additions and 102 deletions

57
.vscode/launch.json vendored
View File

@@ -4,28 +4,35 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "All Tests",
"type": "dart",
"request": "launch",
"program": "test/"
},
{
"name": "Main",
"program": "bin/dw_data.dart",
"request": "launch",
"type": "dart"
},
{
"name": "Example",
"program": "example/example.dart",
"request": "launch",
"type": "dart"
},
{
"name": "Dump Dart",
"program": "scripts/dump/dump.dart",
"request": "launch",
"type": "dart"
}, ]
}
{
"name": "Dart - Current File",
"type": "dart",
"request": "launch",
"program": "${file}"
},
{
"name": "All Tests",
"type": "dart",
"request": "launch",
"program": "test/"
},
{
"name": "Main",
"program": "bin/dw_data.dart",
"request": "launch",
"type": "dart"
},
{
"name": "Example",
"program": "example/example.dart",
"request": "launch",
"type": "dart"
},
{
"name": "Dump Dart",
"program": "scripts/dump/dump.dart",
"request": "launch",
"type": "dart"
},
]
}

View File

@@ -1,7 +1,7 @@
# Defines a default set of lint rules enforced for
# projects at Google. For details and rationale,
# see https://github.com/dart-lang/pedantic#enabled-lints.
include: package:pedantic/analysis_options.yaml
include: package:lints/recommended.yaml
analyzer:
exclude:
- example/*.dart

3
lib/_utils/uuid.dart Normal file
View File

@@ -0,0 +1,3 @@
import 'package:uuid/uuid.dart';
String uuid() => Uuid().v4();

88
lib/alignment.dart Normal file
View File

@@ -0,0 +1,88 @@
import 'dart:convert';
class AlignmentValue {
AlignmentValue({
required this.key,
required this.description,
});
final String key;
final String description;
AlignmentValue copyWith({
String? key,
String? description,
}) =>
AlignmentValue(
key: key ?? this.key,
description: description ?? this.description,
);
factory AlignmentValue.fromRawJson(String str) =>
AlignmentValue.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AlignmentValue.fromJson(Map<String, dynamic> json) => AlignmentValue(
key: json["key"],
description: json["description"],
);
Map<String, dynamic> toJson() => {
"key": key,
"description": description,
};
}
class AlignmentValues {
AlignmentValues({
required this.good,
required this.evil,
required this.lawful,
required this.neutral,
required this.chaotic,
});
final String good;
final String evil;
final String lawful;
final String neutral;
final String chaotic;
AlignmentValues copyWith({
String? good,
String? evil,
String? lawful,
String? neutral,
String? chaotic,
}) =>
AlignmentValues(
good: good ?? this.good,
evil: evil ?? this.evil,
lawful: lawful ?? this.lawful,
neutral: neutral ?? this.neutral,
chaotic: chaotic ?? this.chaotic,
);
factory AlignmentValues.fromRawJson(String str) =>
AlignmentValues.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AlignmentValues.fromJson(Map<String, dynamic> json) =>
AlignmentValues(
good: json["good"],
evil: json["evil"],
lawful: json["lawful"],
neutral: json["neutral"],
chaotic: json["chaotic"],
);
Map<String, dynamic> toJson() => {
"good": good,
"evil": evil,
"lawful": lawful,
"neutral": neutral,
"chaotic": chaotic,
};
}

40
lib/bond.dart Normal file
View File

@@ -0,0 +1,40 @@
import 'dart:convert';
class Bond {
Bond({
required this.key,
required this.description,
required this.completed,
});
final String key;
final String description;
final bool completed;
Bond copyWith({
String? key,
String? description,
bool? completed,
}) =>
Bond(
key: key ?? this.key,
description: description ?? this.description,
completed: completed ?? this.completed,
);
factory Bond.fromRawJson(String str) => Bond.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Bond.fromJson(Map<String, dynamic> json) => Bond(
key: json["key"],
completed: json["completed"],
description: json["description"],
);
Map<String, dynamic> toJson() => {
"key": key,
"description": description,
"completed": completed,
};
}

89
lib/character_class.dart Normal file
View File

@@ -0,0 +1,89 @@
import 'dart:convert';
import 'alignment.dart';
import 'dice.dart';
import 'gear_choice.dart';
class CharacterClass {
CharacterClass({
required this.meta,
required this.name,
required this.key,
required this.description,
required this.damageDice,
required this.load,
required this.hp,
required this.alignments,
required this.bonds,
required this.gearChoices,
});
final dynamic meta;
final String name;
final String key;
final String description;
final Dice damageDice;
final int load;
final int hp;
final AlignmentValues alignments;
final List<String> bonds;
final List<GearChoice> gearChoices;
CharacterClass copyWith({
dynamic meta,
String? name,
String? key,
String? description,
Dice? damageDice,
int? load,
int? hp,
AlignmentValues? alignments,
List<String>? bonds,
List<GearChoice>? gearChoices,
}) =>
CharacterClass(
meta: meta ?? this.meta,
name: name ?? this.name,
key: key ?? this.key,
description: description ?? this.description,
damageDice: damageDice ?? this.damageDice,
load: load ?? this.load,
hp: hp ?? this.hp,
alignments: alignments ?? this.alignments,
bonds: bonds ?? this.bonds,
gearChoices: gearChoices ?? this.gearChoices,
);
factory CharacterClass.fromRawJson(String str) =>
CharacterClass.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory CharacterClass.fromJson(Map<String, dynamic> json) => CharacterClass(
meta: json['_meta'],
name: json["name"],
key: json["key"],
description: json["description"],
damageDice: Dice.fromJson(json["damageDice"]),
load: json["load"],
hp: json["hp"],
alignments: AlignmentValues.fromJson(json["alignments"]),
bonds: List<String>.from(json["bonds"].map((x) => x)),
gearChoices: List<GearChoice>.from(
json["gearChoices"].map((x) => GearChoice.fromJson(x)),
),
);
Map<String, dynamic> toJson() => {
"_meta": meta,
"name": name,
"key": key,
"description": description,
"damageDice": damageDice.toJson(),
"load": load,
"hp": hp,
"alignments": alignments.toJson(),
"bonds": List<dynamic>.from(bonds.map((x) => x)),
"gearChoices": List<dynamic>.from(gearChoices.map((x) => x.toJson())),
};
}

105
lib/dice.dart Normal file
View File

@@ -0,0 +1,105 @@
import 'dart:convert';
import 'dart:math';
class Dice {
Dice({
required this.amount,
required this.sides,
this.modifier,
});
final int amount;
final int sides;
final int? modifier;
Dice copyWith({
int? amount,
int? sides,
int? modifier,
}) =>
Dice(
amount: amount ?? this.amount,
sides: sides ?? this.sides,
modifier: modifier ?? this.modifier,
);
factory Dice.fromRawJson(String str) => Dice.fromJson(json.decode(str));
static Dice d4 = Dice(amount: 1, sides: 4);
static Dice d6 = Dice(amount: 1, sides: 6);
static Dice d8 = Dice(amount: 1, sides: 8);
static Dice d10 = Dice(amount: 1, sides: 10);
static Dice d12 = Dice(amount: 1, sides: 12);
static Dice d20 = Dice(amount: 1, sides: 20);
static Dice d60 = Dice(amount: 1, sides: 60);
static Dice d100 = Dice(amount: 1, sides: 100);
String toRawJson() => toJson();
factory Dice.fromJson(String json) {
var parts = json.split("d");
var amount = int.tryParse(parts[0]);
int? sides;
int? modifier;
if (parts[1].contains(RegExp(r'[-+]'))) {
var idx = parts[1].indexOf(RegExp(r'[^0-9]'));
sides = int.tryParse(parts[1].substring(0, idx));
modifier = int.tryParse(parts[1].substring(idx));
} else {
sides = int.tryParse(parts[1]);
}
if (sides == null || amount == null) {
throw Exception("Dice parsing failed");
}
return Dice(
amount: amount,
sides: sides,
modifier: modifier,
);
}
@override
String toString() => "${amount}d$sides$modifierWithSign";
String toJson() => toString();
String get modifierWithSign => modifier == null
? ""
: modifier! > 0
? "+$modifier"
: "$modifier";
DiceResult roll() => DiceResult.roll(this);
operator *(int amount) => copyWith(amount: this.amount * amount);
operator /(int amount) => copyWith(amount: this.amount ~/ amount);
}
class DiceResult {
final Dice dice;
final List<int> results;
DiceResult({required this.dice, required this.results});
static List<DiceResult> rollMany(List<Dice> dice) {
return dice.map((d) {
var arr = <int>[];
for (var i = 0; i < d.amount; i++) {
arr.add(Random().nextInt(d.sides));
}
return DiceResult(dice: d, results: arr);
}).toList();
}
int get total =>
results.reduce((all, cur) => all + cur) + (dice.modifier ?? 0);
bool get didHitNaturalMax => indexOfNaturalMax >= 0;
int get indexOfNaturalMax => results.indexOf(dice.sides);
static DiceResult roll(Dice dice) {
return rollMany([dice])[0];
}
}

View File

@@ -0,0 +1,12 @@
export 'alignment.dart';
export 'bond.dart';
export 'bond.dart';
export 'character_class.dart';
export 'dice.dart';
export 'gear_choice.dart';
export 'gear_selection.dart';
export 'item.dart';
export 'move.dart';
export 'race.dart';
export 'spell.dart';
export 'tag.dart';

44
lib/gear_choice.dart Normal file
View File

@@ -0,0 +1,44 @@
import 'dart:convert';
import 'gear_selection.dart';
class GearChoice {
GearChoice({
required this.key,
required this.description,
required this.selections,
});
final String key;
final String description;
final List<GearSelection> selections;
GearChoice copyWith({
String? key,
String? description,
List<GearSelection>? selections,
}) =>
GearChoice(
key: key ?? this.key,
description: description ?? this.description,
selections: selections ?? this.selections,
);
factory GearChoice.fromRawJson(String str) =>
GearChoice.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GearChoice.fromJson(Map<String, dynamic> json) => GearChoice(
key: json["key"],
description: json["description"],
selections: List<GearSelection>.from(
json["selections"].map((x) => GearSelection.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"key": key,
"description": description,
"selections": List<dynamic>.from(selections.map((x) => x.toJson())),
};
}

37
lib/gear_option.dart Normal file
View File

@@ -0,0 +1,37 @@
import 'dart:convert';
import 'item.dart';
class GearOption {
GearOption({
required this.item,
required this.amount,
});
final Item item;
final double amount;
GearOption copyWith({
Item? item,
double? amount,
}) =>
GearOption(
item: item ?? this.item,
amount: amount ?? this.amount,
);
factory GearOption.fromRawJson(String str) =>
GearOption.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GearOption.fromJson(Map<String, dynamic> json) => GearOption(
item: json["item"],
amount: json["amount"],
);
Map<String, dynamic> toJson() => {
"item": item,
"amount": amount,
};
}

45
lib/gear_selection.dart Normal file
View File

@@ -0,0 +1,45 @@
import 'dart:convert';
import 'gear_option.dart';
import 'item.dart';
class GearSelection {
GearSelection({
required this.description,
required this.items,
required this.gold,
});
final String description;
final List<GearOption> items;
final int gold;
GearSelection copyWith({
String? description,
List<GearOption>? items,
int? gold,
}) =>
GearSelection(
description: description ?? this.description,
items: items ?? this.items,
gold: gold ?? this.gold,
);
factory GearSelection.fromRawJson(String str) =>
GearSelection.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GearSelection.fromJson(Map<String, dynamic> json) => GearSelection(
description: json["description"],
items: List<GearOption>.from(
json["items"].map((x) => GearOption.fromJson(x))),
gold: json["gold"],
);
Map<String, dynamic> toJson() => {
"description": description,
"items": List<dynamic>.from(items.map((x) => x.toJson())),
"gold": gold,
};
}

53
lib/item.dart Normal file
View File

@@ -0,0 +1,53 @@
import 'dart:convert';
import 'tag.dart';
class Item {
Item({
required this.meta,
required this.key,
required this.description,
required this.name,
required this.tags,
});
final dynamic meta;
final String key;
final String name;
final String description;
final List<Tag> tags;
Item copyWith({
dynamic meta,
String? key,
String? name,
List<Tag>? tags,
}) =>
Item(
meta: meta ?? this.meta,
key: key ?? this.key,
name: name ?? this.name,
description: description ?? this.description,
tags: tags ?? this.tags,
);
factory Item.fromRawJson(String str) => Item.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Item.fromJson(Map<String, dynamic> json) => Item(
meta: json["_meta"],
key: json["key"],
name: json["name"],
description: json["description"],
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"_meta": meta,
"key": key,
"name": name,
"description": description,
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
};
}

View File

@@ -0,0 +1,38 @@
class Repository {}
class RepositoryItem<T> {
final Map<String, Map<String, T>> _cache = {};
String currentLocale;
RepositoryItem({
required this.currentLocale,
});
List<T> get list {
_ensureLocale(currentLocale);
return _cache[currentLocale]!.values.toList();
}
Map<String, T> get map {
_ensureLocale(currentLocale);
return _cache[currentLocale]!;
}
void registerLocale(String locale) {
if (_cache[locale] != null) {
return;
}
_cache[locale] = {};
}
void addItems(String locale, Map<String, T> items) {
_ensureLocale(locale);
_cache[locale]!.addAll(items);
}
void _ensureLocale(String locale) {
if (_cache[locale] == null) {
throw Exception('Locale $locale does not exist.');
}
}
}

67
lib/monster.dart Normal file
View File

@@ -0,0 +1,67 @@
import 'dart:convert';
import 'move.dart';
import 'tag.dart';
class Monster {
Monster({
required this.meta,
required this.key,
required this.name,
required this.description,
required this.instinct,
required this.tags,
required this.moves,
});
final dynamic meta;
final String key;
final String name;
final String description;
final String instinct;
final List<Tag> tags;
final List<String> moves;
Monster copyWith({
dynamic meta,
String? key,
String? name,
String? description,
String? instinct,
List<Tag>? tags,
List<String>? moves,
}) =>
Monster(
meta: meta ?? this.meta,
key: key ?? this.key,
name: name ?? this.name,
description: description ?? this.description,
instinct: instinct ?? this.instinct,
tags: tags ?? this.tags,
moves: moves ?? this.moves,
);
factory Monster.fromRawJson(String str) => Monster.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Monster.fromJson(Map<String, dynamic> json) => Monster(
meta: json["_meta"],
key: json["key"],
name: json["name"],
description: json["description"],
instinct: json["instinct"],
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
moves: json["moves"].map((x) => x),
);
Map<String, dynamic> toJson() => {
"_meta": meta,
"key": key,
"name": name,
"description": description,
"instinct": instinct,
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
"moves": moves,
};
}

88
lib/move.dart Normal file
View File

@@ -0,0 +1,88 @@
import 'dart:convert';
import 'dice.dart';
import 'tag.dart';
enum MoveCategory {
starting,
basic,
advanced1,
advanced2,
other,
}
class Move {
Move({
required this.meta,
required this.key,
required this.name,
required this.description,
required this.explanation,
required this.dice,
required this.classKeys,
required this.tags,
required this.category,
});
final dynamic meta;
final String key;
final String name;
final String description;
final String explanation;
final List<Dice> dice;
final List<String> classKeys;
final List<Tag> tags;
final MoveCategory category;
Move copyWith({
dynamic meta,
String? key,
String? name,
String? description,
String? explanation,
List<Dice>? dice,
List<String>? classKeys,
List<Tag>? tags,
MoveCategory? category,
}) =>
Move(
meta: meta ?? this.meta,
key: key ?? this.key,
name: name ?? this.name,
description: description ?? this.description,
explanation: explanation ?? this.explanation,
dice: dice ?? this.dice,
classKeys: classKeys ?? this.classKeys,
tags: tags ?? this.tags,
category: category ?? this.category,
);
factory Move.fromRawJson(String str) => Move.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Move.fromJson(Map<String, dynamic> json) => Move(
meta: json["_meta"],
key: json["key"],
name: json["name"],
description: json["description"],
explanation: json["explanation"],
dice: List<Dice>.from(json["dice"].map((x) => x.toJson())),
classKeys: List<String>.from(json["classKeys"].map((x) => x)),
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
category: MoveCategory.values
.firstWhere((element) => element.name == json["category"]),
);
Map<String, dynamic> toJson() => {
"_meta": meta,
"key": key,
"name": name,
"description": description,
"explanation": explanation,
"dice": List<String>.from(dice.map((x) => x.toJson())),
"classKeys": List<dynamic>.from(classKeys.map((x) => x)),
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
"category": category.name,
};
}

66
lib/race.dart Normal file
View File

@@ -0,0 +1,66 @@
import 'dart:convert';
import 'tag.dart';
class Race {
Race({
required this.meta,
required this.key,
required this.name,
required this.description,
required this.explanation,
required this.classKeys,
required this.tags,
});
final dynamic meta;
final String key;
final String name;
final String description;
final String explanation;
final List<String> classKeys;
final List<Tag> tags;
Race copyWith({
dynamic meta,
String? key,
String? name,
String? description,
String? explanation,
List<String>? classKeys,
List<Tag>? tags,
}) =>
Race(
meta: meta ?? this.meta,
key: key ?? this.key,
name: name ?? this.name,
description: description ?? this.description,
explanation: explanation ?? this.explanation,
classKeys: classKeys ?? this.classKeys,
tags: tags ?? this.tags,
);
factory Race.fromRawJson(String str) => Race.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Race.fromJson(Map<String, dynamic> json) => Race(
meta: json["_meta"],
key: json["key"],
name: json["name"],
description: json["description"],
explanation: json["explanation"],
classKeys: List<String>.from(json["classKeys"].map((x) => x)),
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"_meta": meta,
"key": key,
"name": name,
"description": description,
"explanation": explanation,
"classKeys": List<dynamic>.from(classKeys.map((x) => x)),
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
};
}

66
lib/spell.dart Normal file
View File

@@ -0,0 +1,66 @@
import 'dart:convert';
import 'tag.dart';
class Spell {
Spell({
required this.meta,
required this.key,
required this.name,
required this.description,
required this.explanation,
required this.classKeys,
required this.tags,
});
final dynamic meta;
final String key;
final String name;
final String description;
final String explanation;
final List<String> classKeys;
final List<Tag> tags;
Spell copyWith({
dynamic meta,
String? key,
String? name,
String? description,
String? explanation,
List<String>? classKeys,
List<Tag>? tags,
}) =>
Spell(
meta: meta ?? this.meta,
key: key ?? this.key,
name: name ?? this.name,
description: description ?? this.description,
explanation: explanation ?? this.explanation,
classKeys: classKeys ?? this.classKeys,
tags: tags ?? this.tags,
);
factory Spell.fromRawJson(String str) => Spell.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Spell.fromJson(Map<String, dynamic> json) => Spell(
meta: json["_meta"],
key: json["key"],
name: json["name"],
description: json["description"],
explanation: json["explanation"],
classKeys: List<String>.from(json["classKeys"].map((x) => x)),
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"_meta": meta,
"key": key,
"name": name,
"description": description,
"explanation": explanation,
"classKeys": List<dynamic>.from(classKeys.map((x) => x)),
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
};
}

40
lib/tag.dart Normal file
View File

@@ -0,0 +1,40 @@
import 'dart:convert';
class Tag {
Tag({
required this.name,
required this.value,
this.description = "",
});
final String name;
final dynamic value;
final String description;
Tag copyWith({
String? name,
dynamic value,
String? description,
}) =>
Tag(
name: name ?? this.name,
value: value ?? this.value,
description: description ?? this.description,
);
factory Tag.fromRawJson(String str) => Tag.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Tag.fromJson(Map<String, dynamic> json) => Tag(
name: json["name"],
value: json["value"],
description: json["description"] ?? "",
);
Map<String, dynamic> toJson() => {
"name": name,
"value": value,
"description": description,
};
}

View File

@@ -92,13 +92,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
glob:
dependency: transitive
description:
@@ -135,7 +128,7 @@ packages:
source: hosted
version: "0.6.3"
lints:
dependency: transitive
dependency: "direct dev"
description:
name: lints
url: "https://pub.dartlang.org"

View File

@@ -8,13 +8,13 @@ environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
collection: ^1.15.0-nullsafety.4
meta: ^1.1.0
quiver: ^3.0.1
uuid: ^3.0.4
collection: ^1.15.0-nullsafety.4
dev_dependencies:
flutter_lints: ^1.0.4
lints: ^1.0.1
dart_style: ^2.0.3
path: ^1.6.4
test: ^1.6.4

View File

@@ -0,0 +1,242 @@
import 'dart:convert';
import 'dart:io';
import 'package:dungeon_world_data/_old/dw_data.dart' as old;
import 'package:dungeon_world_data/_utils/uuid.dart';
import 'package:dungeon_world_data/dungeon_world_data.dart';
import 'package:dungeon_world_data/gear_option.dart';
import 'package:dungeon_world_data/monster.dart';
import 'package:path/path.dart' as path;
final _jsonOut = path.join(
path.dirname(Platform.script.path),
'dump.json',
);
Map<String, String> strFixMap = {
"": "-",
"": "-",
"": "'",
"": "\"",
"": "\"",
};
final json = <String, List<Map<String, dynamic>>>{
'moves': [],
'races': [],
'classes': [],
'spells': [],
'items': [],
'monsters': [],
'tags': [],
};
final defaultTags = <Tag>[
Tag(name: "language", value: "EN"),
Tag(name: "source", value: "repo"),
];
main() async {
print("Starting...");
// Basic moves
print("Adding ${old.dungeonWorld.basicMoves.length} basic moves");
for (var move in old.dungeonWorld.basicMoves) {
json['moves']!.add(moveMapper(move, MoveCategory.basic).toJson());
}
for (var cls in old.dungeonWorld.classes) {
// Starting moves
print("Adding ${cls.startingMoves.length} starting moves");
for (var move in cls.startingMoves) {
json['moves']!.add(moveMapper(move, MoveCategory.starting).toJson());
}
// Advanced Moves 1
print("Adding ${cls.advancedMoves1.length} advanced1 moves");
for (var move in cls.advancedMoves1) {
json['moves']!.add(moveMapper(move, MoveCategory.advanced1).toJson());
}
// Advanced Moves 1
print("Adding ${cls.advancedMoves2.length} advanced2 moves");
for (var move in cls.advancedMoves2) {
json['moves']!.add(moveMapper(move, MoveCategory.advanced2).toJson());
}
// Races
print("Adding ${cls.raceMoves.length} races");
for (var race in cls.raceMoves) {
json['races']!
.add(raceMapper(race, cls.key ?? makeKey(cls.name)).toJson());
}
// Classes
json['classes']!.add(classMapper(cls).toJson());
}
print("Total ${json['classes']!.length} classes");
// Spells
print("Adding ${old.dungeonWorld.spells.length} spells");
for (var spell in old.dungeonWorld.spells) {
json['spells']!.add(spellMapper(spell).toJson());
}
print("Adding ${old.dungeonWorld.equipment.length} items");
for (var equip in old.dungeonWorld.equipment) {
json['items']!.add(equipMapper(equip).toJson());
}
print("Adding ${old.dungeonWorld.monsters.length} monsters");
for (var mon in old.dungeonWorld.monsters) {
json['monsters']!.add(monsterMapper(mon).toJson());
}
print("Adding ${old.dungeonWorld.tags.length} tags");
for (var tag in old.dungeonWorld.tags) {
json['tags']!.add(tagMapper(tag).toJson());
}
//
//
await File(_jsonOut).writeAsString(jsonEncode(json));
print("Done");
}
String fix(String? str) {
if (str == null || str.trim().isEmpty) {
return "";
}
for (var _fix in strFixMap.entries) {
str = str!.replaceAll(_fix.key, _fix.value);
}
return str!.trim();
}
String makeKey(String str) {
return fix(str)
.replaceAll(RegExp('["\']'), "")
.replaceAll(RegExp(r'[^a-z]+', caseSensitive: false), '_')
.toLowerCase();
}
Set<Dice> guessDice(String str) {
var basicRollPattern = RegExp(r'\broll\+[a-z]{3}\b', caseSensitive: false);
var dicePattern = RegExp(r'\b\dd\d\b', caseSensitive: false);
var found = <Dice>{};
var basicRollMatches = basicRollPattern.allMatches(str);
for (var match in basicRollMatches) {
found.add(Dice.d6 * 2);
}
var diceMatches = dicePattern.allMatches(str);
for (var match in diceMatches) {
found.add(Dice.fromJson(match.input.substring(match.start, match.end)));
}
return found;
}
Move moveMapper(old.Move move, MoveCategory category) => Move(
category: category,
classKeys: move.classes,
description: fix(move.description),
dice: guessDice(fix(move.description)).toList(),
explanation: fix(move.explanation ?? ""),
key: makeKey(move.name),
meta: null,
name: fix(move.name),
tags: defaultTags,
);
Race raceMapper(old.Move move, String classKey) => Race(
classKeys: [classKey],
description: fix(move.description),
explanation: fix(move.explanation ?? ""),
key: makeKey(move.name),
meta: null,
name: fix(move.name),
tags: defaultTags,
);
Spell spellMapper(old.Spell spell) => Spell(
classKeys: [],
description: fix(spell.description),
explanation: "",
key: makeKey(spell.name),
meta: null,
name: fix(spell.name),
tags: [...defaultTags, ...spell.tags.map((t) => tagMapper(t))],
);
Tag tagMapper(old.Tag t) => Tag.fromJson(t.toJSON().runtimeType == String
? {"name": t.toJSON()}
: {"name": t.name, "value": t.value, "description": fix(t.description)});
Item equipMapper(old.Equipment equip) => Item(
key: makeKey(equip.name),
meta: null,
name: fix(equip.name),
description: fix(equip.description),
tags: equip.tags.map((t) => tagMapper(t)).toList(),
);
Monster monsterMapper(old.Monster move) => Monster(
instinct: fix(move.instinct),
description: fix(move.description),
key: makeKey(move.name),
meta: null,
name: fix(move.name),
tags: defaultTags,
moves: move.moves,
);
CharacterClass classMapper(old.PlayerClass cls) => CharacterClass(
alignments: AlignmentValues(
chaotic: fix(cls.alignments['chaotic']?.description ?? ""),
neutral: fix(cls.alignments['neutral']?.description ?? ""),
evil: fix(cls.alignments['evil']?.description ?? ""),
good: fix(cls.alignments['good']?.description ?? ""),
lawful: fix(cls.alignments['lawful']?.description ?? ""),
),
bonds: cls.bonds.map(fix).toList(),
damageDice: Dice.fromJson(cls.damage.toString()),
description: fix(cls.description),
gearChoices: cls.gearChoices
.map(
(c) => GearChoice(
key: c.key ?? uuid(),
description: fix(c.label),
selections: c.gearOptions
.map(
(o) => GearSelection(
description: o.name + '(TODO: INCOMPLETE)',
items: [
GearOption(
amount: o.name.contains(RegExp(r'[0-9]+'))
? double.tryParse(RegExp(r'[0-9]+')
.firstMatch(o.name)
?.group(0) ??
"1.0") ??
1.0
: 1.0,
item: Item(
key: makeKey(o.name),
meta: null,
name: fix(o.name),
description: fix(o.name),
tags: defaultTags,
),
),
],
gold: 0,
),
)
.toList(),
),
)
.toList(),
hp: cls.baseHP.toInt(),
key: makeKey(cls.name),
load: cls.load.toInt(),
name: cls.name,
meta: null,
);

View File

@@ -1,75 +1,48 @@
import 'package:dungeon_world_data/dw_data.dart';
import 'package:dungeon_world_data/dice.dart';
import 'package:test/test.dart';
void main() {
group('Dice', () {
test('Sides and amount', () {
var expected = Dice(6, 2);
expect(expected.sides, equals(6));
expect(expected.amount, equals(2));
group("Parse JSON", () {
test("No modifier", () {
var str = "1d6";
var dice = Dice.fromJson(str);
expect(dice.amount, equals(1));
expect(dice.sides, equals(6));
expect(dice.modifier, equals(null));
});
test("With positive modifier", () {
var str = "3d8+3";
var dice = Dice.fromJson(str);
expect(dice.amount, equals(3));
expect(dice.sides, equals(8));
expect(dice.modifier, equals(3));
});
test("With negative modifier", () {
var str = "2d20-4";
var dice = Dice.fromJson(str);
expect(dice.amount, equals(2));
expect(dice.sides, equals(20));
expect(dice.modifier, equals(-4));
});
});
test('String representation', () {
var dice1 = Dice(10, 4);
var dice2 = Dice(6, 2, 3);
var dice3 = Dice(20, 2, -4);
expect(dice1.toString(), equals('4d10'));
expect(dice2.toString(), equals('2d6+3'));
expect(dice3.toString(), equals('2d20-4'));
});
test('Multiplication', () {
num amt = 10;
var dice = Dice.d12 * amt;
expect(dice.amount, amt);
});
test('Equality', () {
var compare = {
Dice(4): Dice.d4,
Dice(6): Dice.d6,
Dice(8): Dice.d8,
Dice(10): Dice.d10,
Dice(12): Dice.d12,
Dice(20): Dice.d20,
};
for (var d in compare.keys) {
expect(d, equals(compare[d]));
expect(compare.values.where((el) => el == d).length, equals(1));
}
});
test('Roll', () {
var d1 = Dice.d6;
var d2 = Dice.d12 * 2;
var d3 = Dice.d8 * 3;
var roll1 = d1.getRoll();
var roll2 = d2.getRoll();
var roll3 = d3.getRoll();
expect(roll1.results[0], greaterThanOrEqualTo(1));
expect(roll1.results[0], lessThanOrEqualTo(6));
expect(roll2.results.length, equals(d2.amount));
expect(roll2.results[0], greaterThanOrEqualTo(1));
expect(roll2.results[0], lessThanOrEqualTo(12));
expect(roll2.results[1], greaterThanOrEqualTo(1));
expect(roll2.results[1], lessThanOrEqualTo(12));
expect(roll3.results.length, equals(d3.amount));
expect(roll3.results[0], greaterThanOrEqualTo(1));
expect(roll3.results[0], lessThanOrEqualTo(8));
expect(roll3.results[1], greaterThanOrEqualTo(1));
expect(roll3.results[1], lessThanOrEqualTo(8));
expect(roll3.results[2], greaterThanOrEqualTo(1));
expect(roll3.results[2], lessThanOrEqualTo(8));
});
test('Roll', () {
var dice = Dice.d6;
var roll = dice.getRoll();
expect(roll.results[0], greaterThanOrEqualTo(1));
expect(roll.results[0], lessThanOrEqualTo(6));
group("Dump JSON", () {
test("No modifier", () {
var str = "1d6";
var dice = Dice(amount: 1, sides: 6);
expect(dice.toJson(), equals(str));
});
test("With positive modifier", () {
var str = "3d8+3";
var dice = Dice(amount: 3, sides: 8, modifier: 3);
expect(dice.toJson(), equals(str));
});
test("With negative modifier", () {
var str = "2d20-4";
var dice = Dice(amount: 2, sides: 20, modifier: -4);
expect(dice.toJson(), equals(str));
});
});
});
}