fix(study): a map question names none of Japan's parts before it is answered

The chips above Japan's map (Hokkaidō, Tōhoku, Kantō …) showed while a
prefecture's question was answered: Hokkaidō's and Okinawa's chip was
the answer itself, and the others named the region the prefecture lies
in. A study card now offers them only once checked; tapping the map
still opens the part tapped. The world's continents keep their chips:
shortcuts no question asks for. Writing a question offers them all, as
before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-14 17:27:57 +02:00
commit 4eb2640be6
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
3 changed files with 47 additions and 3 deletions

View file

@ -83,6 +83,13 @@ class const RegionMap({
/// Whether the mouse's wheel zooms without Ctrl (or ⌘): where nothing /// Whether the mouse's wheel zooms without Ctrl (or ⌘): where nothing
/// around the map scrolls. /// around the map scrolls.
final bool wheelZooms = false, final bool wheelZooms = false,
/// Whether a country's own map offers a chip for each of its parts
/// (Japan's Kantō, Kansai …), as while writing a question (decided
/// 2026-10-14). While answering one they would give it away: a part may
/// be the answer itself (Hokkaidō, Okinawa), or name where it lies. The
/// world's continents keep theirs, as shortcuts no question asks for.
final bool namesCountryParts = true,
super.key, super.key,
}) extends StatefulWidget { }) extends StatefulWidget {
@override @override
@ -509,6 +516,7 @@ class RegionMapState()
final above = atlas.above(_level); final above = atlas.above(_level);
final header = _Header( final header = _Header(
level: _level, level: _level,
chips: widget.namesCountryParts || _level.map == atlas.world,
above: above, above: above,
opens: [ opens: [
if (widget.countryTaps == CountryTaps.pickOrOpen && if (widget.countryTaps == CountryTaps.pickOrOpen &&
@ -547,11 +555,12 @@ class RegionMapState()
} }
/// Above the map: Back to the layer [above], if any; on a whole map a chip /// Above the map: Back to the layer [above], if any; on a whole map a chip
/// per group, which opens it; in a group its name, and a chip for each map /// per group, which opens it, unless without [chips]; in a group its name,
/// within a country of it that one may [opens] (Japan's prefectures, once /// and a chip for each map within a country of it that one may [opens]
/// Japan is picked). /// (Japan's prefectures, once Japan is picked).
class const _Header({ class const _Header({
required final MapLevel level, required final MapLevel level,
required final bool chips,
required final MapLevel? above, required final MapLevel? above,
required final List<GeoMap> opens, required final List<GeoMap> opens,
required final VoidCallback? onBack, required final VoidCallback? onBack,
@ -576,6 +585,7 @@ class const _Header({
], ],
Expanded( Expanded(
child: switch (level.group) { child: switch (level.group) {
null when !chips => const SizedBox.shrink(),
null => ListView.separated( null => ListView.separated(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: level.map.groups.length, itemCount: level.map.groups.length,

View file

@ -1365,6 +1365,9 @@ class _MapBodyState() extends State<MapBody> {
countryTaps: atlas.mapOf(right) == atlas.world countryTaps: atlas.mapOf(right) == atlas.world
? CountryTaps.pick ? CountryTaps.pick
: CountryTaps.open, : CountryTaps.open,
// Japan's regions named before the answer would
// give it away.
namesCountryParts: widget.checked,
selected: widget.checked ? null : _picked, selected: widget.checked ? null : _picked,
right: widget.checked ? right : null, right: widget.checked ? right : null,
wrong: widget.checked && _picked != right wrong: widget.checked && _picked != right

View file

@ -28,6 +28,7 @@ void main() {
String? right, String? right,
String? wrong, String? wrong,
bool readOnly = false, bool readOnly = false,
bool namesCountryParts = true,
}) async { }) async {
tester.view tester.view
..physicalSize = const Size(400, 640) ..physicalSize = const Size(400, 640)
@ -52,6 +53,7 @@ void main() {
selected: picked.lastOrNull, selected: picked.lastOrNull,
right: right, right: right,
wrong: wrong, wrong: wrong,
namesCountryParts: namesCountryParts,
onRegionTapped: readOnly onRegionTapped: readOnly
? null ? null
: (code) => setState(() => picked.add(code)), : (code) => setState(() => picked.add(code)),
@ -102,6 +104,35 @@ void main() {
const tokyo = (139.69, 35.69); const tokyo = (139.69, 35.69);
testWidgets("while answering, Japan's parts have no chips, which would "
"name the answer or where it lies; the map opens them at a tap, and the "
"world's continents keep theirs", (tester) async {
final picked = await show(
tester,
countryTaps: CountryTaps.open,
// The questions studied, all prefectures: on the whole of Japan.
around: {'JP-13', 'JP-27'},
namesCountryParts: false,
);
expect(back('East Asia'), findsOneWidget);
expect(chip('Hokkaidō'), findsNothing);
expect(chip('Kantō'), findsNothing);
await tapAt(tester, tokyo);
expect(find.text('Kantō'), findsOneWidget);
await tapAt(tester, tokyo);
expect(picked, ['JP-13']);
await tester.tap(back('Japan'));
await tester.pumpAndSettle();
expect(chip('Okinawa'), findsNothing);
await tester.tap(back('East Asia'));
await tester.pumpAndSettle();
await tester.tap(back('World'));
await tester.pumpAndSettle();
expect(chip('Europe'), findsOneWidget);
});
testWidgets('Japan is picked in East Asia, and once it is, a chip opens ' testWidgets('Japan is picked in East Asia, and once it is, a chip opens '
'its prefectures in layers; Back goes up one', (tester) async { 'its prefectures in layers; Back goes up one', (tester) async {
final picked = await show(tester); final picked = await show(tester);