Skip to content

Commit 892166e

Browse files
authored
Make results classes fields non-nullable (#4)
* Make all RollResult/RollStatistics fields required * Move files to src, to import it once as library * Use pedantic * Update examples * Bump version
1 parent cd14db4 commit 892166e

File tree

11 files changed

+224
-325
lines changed

11 files changed

+224
-325
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# CHANGELOG
22

3+
## 0.3.0
4+
- Make some results fields non-nullable, 💅 to analysis_options.
5+
36
## 0.2.0-nullsafety.0
47
- Migrate to nullsafety.
58

README.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,33 @@
44
</p>
55

66
<!-- Badges -->
7+
[![View at pub.dev][pub-badge]][pub-link]
8+
[![Test][actions-badge]][actions-link]
9+
[![PRs Welcome][prs-badge]][prs-link]
10+
[![Star on GitHub][github-star-badge]][github-star-link]
11+
[![Fork on GitHub][github-forks-badge]][github-forks-link]
712

8-
[![Pub Package](https://img.shields.io/pub/v/d20.svg)](https://pub.dartlang.org/packages/d20)
9-
[![CircleCI](https://circleci.com/gh/Igor1201/d20/tree/master.svg?style=svg&circle-token=376c1d43be17c8602903dfc02368f711ea1a4ed6)](https://circleci.com/gh/Igor1201/d20/tree/master)
13+
[pub-badge]: https://img.shields.io/pub/v/d20?style=for-the-badge
14+
[pub-link]: https://pub.dev/packages/d20
15+
16+
[actions-badge]: https://img.shields.io/github/workflow/status/comigor/d20/CI?style=for-the-badge
17+
[actions-link]: https://github.com/comigor/d20/actions
18+
19+
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge
20+
[prs-link]: https://github.com/comigor/d20/issues
21+
22+
[github-star-badge]: https://img.shields.io/github/stars/comigor/d20.svg?style=for-the-badge&logo=github&logoColor=ffffff
23+
[github-star-link]: https://github.com/comigor/d20/stargazers
24+
25+
[github-forks-badge]: https://img.shields.io/github/forks/comigor/d20.svg?style=for-the-badge&logo=github&logoColor=ffffff
26+
[github-forks-link]: https://github.com/comigor/d20/network/members
1027

1128
D20 is a Dart library for RPG dice rolling. Supports standard notation (like "2d12", "d6+5" and "2d20-L").
1229

1330
## Installation
14-
add the following to your `pubspec.yaml` file:
15-
```shell
31+
32+
Add the following to your `pubspec.yaml` file:
33+
```yaml
1634
dependencies:
1735
d20: <1.0.0
1836
```
@@ -31,7 +49,7 @@ flutter packages get
3149
import 'package:d20/d20.dart';
3250
3351
void main() {
34-
final D20 d20 = D20();
52+
final d20 = D20();
3553
print(d20.roll('2d8+5+5d6'));
3654
}
3755
@@ -40,18 +58,16 @@ void main() {
4058
One can also get (probably) useful information of roll results:
4159
```dart
4260
import 'package:d20/d20.dart';
43-
import 'package:d20/roll_statistics.dart';
4461
4562
void main() {
46-
final D20 d20 = D20();
47-
final RollStatistics stats = d20.rollWithStatistics('2d8+5+5d6');
63+
final d20 = D20();
64+
final stats = d20.rollWithStatistics('2d8+5+5d6');
4865
print(stats.results[0].faces);
4966
print(stats.results[1].results);
5067
}
5168
5269
```
5370

54-
5571
## Supported notation
5672
The [standard dice notation](https://en.wikipedia.org/wiki/Dice_notation) will be parsed, such as 2d8+4.
5773

analysis_options.yaml

Lines changed: 6 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,10 @@
11
# https://www.dartlang.org/guides/language/analysis-options
2-
# Source of linter options:
3-
# http://dart-lang.github.io/linter/lints/options/options.html
2+
3+
include: package:pedantic/analysis_options.yaml
4+
45
analyzer:
56
strong-mode:
67
implicit-casts: false
7-
errors:
8-
todo: ignore
9-
unused_element: error
10-
unused_import: error
11-
unused_local_variable: error
12-
dead_code: error
13-
linter:
14-
rules:
15-
- always_declare_return_types
16-
- always_put_control_body_on_new_line
17-
- always_put_required_named_parameters_first
18-
- always_require_non_null_named_parameters
19-
- always_specify_types
20-
- annotate_overrides
21-
- avoid_annotating_with_dynamic
22-
- avoid_as
23-
- avoid_bool_literals_in_conditional_expressions
24-
- avoid_catches_without_on_clauses
25-
- avoid_catching_errors
26-
- avoid_classes_with_only_static_members
27-
- avoid_double_and_int_checks
28-
- avoid_empty_else
29-
- avoid_field_initializers_in_const_classes
30-
- avoid_function_literals_in_foreach_calls
31-
- avoid_init_to_null
32-
- avoid_js_rounded_ints
33-
- avoid_null_checks_in_equality_operators
34-
- avoid_positional_boolean_parameters
35-
- avoid_private_typedef_functions
36-
- avoid_relative_lib_imports
37-
- avoid_renaming_method_parameters
38-
- avoid_return_types_on_setters
39-
- avoid_returning_null
40-
- avoid_returning_this
41-
- avoid_setters_without_getters
42-
- avoid_single_cascade_in_expression_statements
43-
- avoid_slow_async_io
44-
- avoid_types_as_parameter_names
45-
# - avoid_types_on_closure_parameters
46-
- avoid_unused_constructor_parameters
47-
- await_only_futures
48-
- camel_case_types
49-
- cancel_subscriptions
50-
- cascade_invocations
51-
- close_sinks
52-
- comment_references
53-
- constant_identifier_names
54-
- control_flow_in_finally
55-
- curly_braces_in_flow_control_structures
56-
- directives_ordering
57-
- empty_catches
58-
- empty_constructor_bodies
59-
- empty_statements
60-
- file_names
61-
- hash_and_equals
62-
- implementation_imports
63-
- invariant_booleans
64-
- iterable_contains_unrelated_type
65-
- join_return_with_assignment
66-
- library_names
67-
- library_prefixes
68-
- lines_longer_than_80_chars
69-
- list_remove_unrelated_type
70-
- literal_only_boolean_expressions
71-
- no_adjacent_strings_in_list
72-
- no_duplicate_case_values
73-
- non_constant_identifier_names
74-
- null_closures
75-
# - omit_local_variable_types
76-
- one_member_abstracts
77-
- only_throw_errors
78-
- overridden_fields
79-
- package_api_docs
80-
- package_names
81-
- package_prefixed_library_names
82-
- parameter_assignments
83-
- prefer_adjacent_string_concatenation
84-
- prefer_asserts_in_initializer_lists
85-
# - prefer_bool_in_asserts
86-
- prefer_collection_literals
87-
- prefer_conditional_assignment
88-
- prefer_const_constructors
89-
- prefer_const_constructors_in_immutables
90-
- prefer_const_declarations
91-
- prefer_const_literals_to_create_immutables
92-
- prefer_constructors_over_static_methods
93-
- prefer_contains
94-
- prefer_equal_for_default_values
95-
- prefer_expression_function_bodies
96-
- prefer_final_fields
97-
- prefer_final_locals
98-
- prefer_foreach
99-
- prefer_function_declarations_over_variables
100-
- prefer_generic_function_type_aliases
101-
- prefer_initializing_formals
102-
- prefer_interpolation_to_compose_strings
103-
- prefer_is_empty
104-
- prefer_is_not_empty
105-
- prefer_iterable_whereType
106-
- prefer_single_quotes
107-
- prefer_typing_uninitialized_variables
108-
- public_member_api_docs
109-
- recursive_getters
110-
- slash_for_doc_comments
111-
- sort_constructors_first
112-
- sort_unnamed_constructors_first
113-
# - super_goes_last
114-
- test_types_in_equals
115-
- throw_in_finally
116-
- type_annotate_public_apis
117-
- type_init_formals
118-
- unawaited_futures
119-
- unnecessary_brace_in_string_interps
120-
- unnecessary_const
121-
- unnecessary_getters_setters
122-
- unnecessary_lambdas
123-
- unnecessary_new
124-
- unnecessary_null_aware_assignments
125-
- unnecessary_null_in_if_null_operators
126-
- unnecessary_overrides
127-
- unnecessary_parenthesis
128-
- unnecessary_statements
129-
- unnecessary_this
130-
- unrelated_type_equality_checks
131-
- use_rethrow_when_possible
132-
- use_setters_to_change_properties
133-
- use_string_buffers
134-
- use_to_and_as_if_applicable
135-
- valid_regexps
136-
- void_checks
8+
exclude:
9+
- example/**/*.dart
10+
- test/**/*.dart

example/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:d20/d20.dart';
22

33
void main() {
4-
final D20 d20 = D20();
4+
final d20 = D20();
55
print(d20.roll('2d8+5+5d6'));
66
}

example/main_statistics.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import 'package:d20/d20.dart';
2-
import 'package:d20/roll_statistics.dart';
32

43
void main() {
5-
final D20 d20 = D20();
6-
final RollStatistics stats = d20.rollWithStatistics('2d8+5+5d6');
7-
print(stats.results![0].faces);
8-
print(stats.results![1].results);
4+
final d20 = D20();
5+
final stats = d20.rollWithStatistics('2d8+5+5d6');
6+
print(stats.results[0].faces);
7+
print(stats.results[1].results);
98
}

lib/d20.dart

Lines changed: 3 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,3 @@
1-
/// Dart library for RPG dice rolling.
2-
///
3-
/// Import this library as follows:
4-
///
5-
/// ```
6-
/// import 'package:d20/d20.dart';
7-
/// ```
8-
9-
import 'dart:math';
10-
import 'package:math_expressions/math_expressions.dart';
11-
import 'roll_result.dart';
12-
import 'roll_statistics.dart';
13-
14-
/// An expression-capable dice roller.
15-
///
16-
/// Simple usage:
17-
/// ```
18-
/// final D20 d20 = D20();
19-
/// d20.roll('2d6+3');
20-
/// ```
21-
///
22-
/// See also [rollWithStatistics], [RollStatistics] and [RollResult].
23-
class D20 {
24-
/// Creates a dice roller.
25-
///
26-
/// Optionally receives a [Random].
27-
D20({Random? random}) {
28-
_random = random == null ? Random() : random;
29-
}
30-
31-
final Parser _parser = Parser();
32-
final ContextModel _context = ContextModel();
33-
34-
/// A [Random] instance that can be customized for seeding.
35-
late Random _random;
36-
37-
RollResult _rollSingleDie(Match match) {
38-
final int numberOfRolls = match[1] == null ? 1 : int.parse(match[1]!);
39-
final int faces = int.parse(match[2]!);
40-
final List<int> results = List<int>.filled(numberOfRolls, faces)
41-
.map((int die) => _random.nextInt(die) + 1)
42-
.toList();
43-
44-
int sum = results.fold(0, (int sum, int roll) => sum + roll);
45-
46-
if (match[3] == '-l') {
47-
sum -= results.fold<int>(faces, min);
48-
} else if (match[3] == '-h') {
49-
sum -= results.fold<int>(0, max);
50-
}
51-
52-
return RollResult(
53-
rollNotation: match[0],
54-
faces: faces,
55-
numberOfRolls: numberOfRolls,
56-
results: results,
57-
finalResult: sum,
58-
);
59-
}
60-
61-
String _sanitizeStringNotation(String dirty) => dirty
62-
.toLowerCase()
63-
.replaceAll(RegExp(r'\s'), '')
64-
.replaceAll(RegExp(r'd%'), 'd100');
65-
66-
/// Compute and return a [RollStatistics] with all information from a roll,
67-
/// including the result from each individual dice roll within.
68-
///
69-
/// See [RollStatistics] and [RollResult] for more info.
70-
RollStatistics rollWithStatistics(String roll) {
71-
final String sanitizedRoll = _sanitizeStringNotation(roll);
72-
73-
final Iterable<Match> matches =
74-
RegExp(r'(\d+)?d(\d+)(-[l|h])?').allMatches(sanitizedRoll);
75-
76-
String newRoll = sanitizedRoll;
77-
final List<RollResult> results = <RollResult>[];
78-
79-
for (int i = matches.length - 1; i >= 0; i--) {
80-
final RollResult result = _rollSingleDie(matches.elementAt(i));
81-
results.add(result);
82-
newRoll = newRoll.replaceRange(matches.elementAt(i).start,
83-
matches.elementAt(i).end, result.finalResult.toString());
84-
}
85-
86-
final double exactResult = _parser
87-
.parse(newRoll)
88-
// ignore: avoid_as
89-
.evaluate(EvaluationType.REAL, _context) as double;
90-
91-
return RollStatistics(
92-
rollNotation: sanitizedRoll,
93-
results: results,
94-
finalResult: exactResult.round(),
95-
);
96-
}
97-
98-
/// Compute an arithmetic expression from a roll defined on standard notation
99-
/// format.
100-
///
101-
/// Example:
102-
/// ```
103-
/// d20.roll('2d6+3');
104-
/// d20.roll('2d20-L');
105-
/// d20.roll('d% * 8');
106-
/// d20.roll('cos(2 * 5d20)');
107-
/// ```
108-
int roll(String roll) {
109-
final String newRoll = _sanitizeStringNotation(roll).replaceAllMapped(
110-
RegExp(r'(\d+)?d(\d+)(-[l|h])?'),
111-
(Match m) => _rollSingleDie(m).finalResult.toString());
112-
113-
final double exactResult = _parser
114-
.parse(newRoll)
115-
// ignore: avoid_as
116-
.evaluate(EvaluationType.REAL, _context) as double;
117-
118-
return exactResult.round();
119-
}
120-
}
1+
export 'src/d20.dart';
2+
export 'src/roll_result.dart';
3+
export 'src/roll_statistics.dart';

0 commit comments

Comments
 (0)