rigor
This commit is contained in:
parent
23cbff14b7
commit
d737e04f47
2 changed files with 171 additions and 18 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'whatfreewords_cipher.dart';
|
import 'whatfreewords_cipher.dart';
|
||||||
|
|
||||||
Map<String, String> ilist =
|
final Map<String, String> ilist =
|
||||||
wlist.map((key, value) => MapEntry(value, key));
|
wlist.map((key, value) => MapEntry(value, key));
|
||||||
|
|
||||||
String f(String L, String R) {
|
String f(String L, String R) {
|
||||||
|
|
@ -19,6 +19,11 @@ String f(String L, String R) {
|
||||||
"2807694315",
|
"2807694315",
|
||||||
"8746293105"
|
"8746293105"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (x < 0 || x >= 10 || y < 0 || y >= 10) {
|
||||||
|
throw RangeError("Index out of bounds: x=$x, y=$y");
|
||||||
|
}
|
||||||
|
|
||||||
return block[y][x];
|
return block[y][x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,10 +31,15 @@ String F(String L, String K) {
|
||||||
int x = int.parse(L);
|
int x = int.parse(L);
|
||||||
int k = int.parse(K);
|
int k = int.parse(K);
|
||||||
String temp = "${x * x * x * k * 3 + 23 * k * k * x * x * x + k * (x + k) + 3}";
|
String temp = "${x * x * x * k * 3 + 23 * k * k * x * x * x + k * (x + k) + 3}";
|
||||||
|
|
||||||
|
temp = temp.padLeft(10, '0');
|
||||||
|
|
||||||
return temp.substring(4, 10);
|
return temp.substring(4, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
String feistPass(String input, String k) {
|
String feistPass(String input, String k) {
|
||||||
|
assert(input.length == 12, "Input to feistPass must be 12 characters long");
|
||||||
|
|
||||||
String L = input.substring(0, 6);
|
String L = input.substring(0, 6);
|
||||||
String R = input.substring(6, 12);
|
String R = input.substring(6, 12);
|
||||||
String Rout = "";
|
String Rout = "";
|
||||||
|
|
@ -58,6 +68,12 @@ String unscrambler(String input) {
|
||||||
}
|
}
|
||||||
|
|
||||||
String coordToWords(List<double> coordinate) {
|
String coordToWords(List<double> coordinate) {
|
||||||
|
if (coordinate.length != 2 ||
|
||||||
|
coordinate[0] < -90 || coordinate[0] > 90 ||
|
||||||
|
coordinate[1] < -180 || coordinate[1] > 180) {
|
||||||
|
throw ArgumentError("Invalid coordinate values: $coordinate");
|
||||||
|
}
|
||||||
|
|
||||||
int lat = (coordinate[0] * 10000).round() + 900000;
|
int lat = (coordinate[0] * 10000).round() + 900000;
|
||||||
int lon = (coordinate[1] * 10000).round() + 1800000;
|
int lon = (coordinate[1] * 10000).round() + 1800000;
|
||||||
|
|
||||||
|
|
@ -69,25 +85,46 @@ String coordToWords(List<double> coordinate) {
|
||||||
|
|
||||||
String latlonRest = scrambler(latStr.substring(1, 7) + lonStr.substring(1, 7));
|
String latlonRest = scrambler(latStr.substring(1, 7) + lonStr.substring(1, 7));
|
||||||
|
|
||||||
lat = int.parse(lat0 + latlonRest.substring(0, 6));
|
lat = int.parse(lat0 + latlonRest.substring(0, 6).padRight(6, '0'));
|
||||||
lon = int.parse(lon0 + latlonRest.substring(6, 12));
|
lon = int.parse(lon0 + latlonRest.substring(6, 12).padRight(6, '0'));
|
||||||
|
|
||||||
String ind1 = lat.toString().substring(0, 5);
|
String latString = lat.toString().padLeft(7, '0');
|
||||||
String ind2 = lon.toString().substring(0, 5);
|
String lonString = lon.toString().padLeft(7, '0');
|
||||||
String ind3 = "0" + lat.toString().substring(5, 7) + lon.toString().substring(5, 7);
|
|
||||||
|
if (latString.length < 7 || lonString.length < 7) {
|
||||||
|
throw ArgumentError("Coordinate string lengths are incorrect: lat=$latString, lon=$lonString");
|
||||||
|
}
|
||||||
|
|
||||||
|
String ind1 = latString.substring(0, 5);
|
||||||
|
String ind2 = lonString.substring(0, 5);
|
||||||
|
String ind3 = "0" + latString.substring(5, 7) + lonString.substring(5, 7);
|
||||||
|
|
||||||
return "${wlist[ind1]}.${wlist[ind2]}.${wlist[ind3]}";
|
return "${wlist[ind1]}.${wlist[ind2]}.${wlist[ind3]}";
|
||||||
}
|
}
|
||||||
|
|
||||||
List<double> wordsToCoord(String words) {
|
List<double> wordsToCoord(String words) {
|
||||||
List<String> word = words.split(".");
|
List<String> word = words.split(".");
|
||||||
String ind1 = ilist[word[0]]!;
|
|
||||||
String ind2 = ilist[word[1]]!;
|
// Ensure exactly 3 words are provided and each exists in the dictionary
|
||||||
String ind3 = ilist[word[2]]!;
|
if (word.length != 3 || !ilist.containsKey(word[0]) || !ilist.containsKey(word[1]) || !ilist.containsKey(word[2])) {
|
||||||
|
throw ArgumentError("Invalid words format: $words");
|
||||||
|
}
|
||||||
|
|
||||||
|
String? ind1 = ilist[word[0]];
|
||||||
|
String? ind2 = ilist[word[1]];
|
||||||
|
String? ind3 = ilist[word[2]];
|
||||||
|
|
||||||
|
if (ind1 == null || ind2 == null || ind3 == null || ind3.length < 5) {
|
||||||
|
throw ArgumentError("Invalid word mapping for words: $words");
|
||||||
|
}
|
||||||
|
|
||||||
String lat = ind1 + ind3.substring(1, 3);
|
String lat = ind1 + ind3.substring(1, 3);
|
||||||
String lon = ind2 + ind3.substring(3, 5);
|
String lon = ind2 + ind3.substring(3, 5);
|
||||||
|
|
||||||
|
if (lat.length < 7 || lon.length < 7) {
|
||||||
|
throw ArgumentError("Malformed coordinate indices: lat=$lat, lon=$lon");
|
||||||
|
}
|
||||||
|
|
||||||
String latlonRest = lat.substring(1, 7) + lon.substring(1, 7);
|
String latlonRest = lat.substring(1, 7) + lon.substring(1, 7);
|
||||||
latlonRest = unscrambler(latlonRest);
|
latlonRest = unscrambler(latlonRest);
|
||||||
|
|
||||||
|
|
@ -97,9 +134,15 @@ List<double> wordsToCoord(String words) {
|
||||||
double latitude = (int.parse(lat) - 900000) / 10000.0;
|
double latitude = (int.parse(lat) - 900000) / 10000.0;
|
||||||
double longitude = (int.parse(lon) - 1800000) / 10000.0;
|
double longitude = (int.parse(lon) - 1800000) / 10000.0;
|
||||||
|
|
||||||
|
// Additional validation: Ensure valid latitude/longitude range
|
||||||
|
if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) {
|
||||||
|
throw ArgumentError("Computed coordinates out of range: lat=$latitude, lon=$longitude");
|
||||||
|
}
|
||||||
|
|
||||||
return [latitude, longitude];
|
return [latitude, longitude];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
List<double> coordinate = [51.50844113, -0.116708278];
|
List<double> coordinate = [51.50844113, -0.116708278];
|
||||||
String words = coordToWords(coordinate);
|
String words = coordToWords(coordinate);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,125 @@
|
||||||
import 'package:whatfreewords/whatfreewords.dart';
|
import 'dart:math';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
import 'package:whatfreewords/whatfreewords.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('Coordinate to Words and Back', () {
|
|
||||||
final List<double> coord = [51.50844113, -0.116708278];
|
|
||||||
final words = coordToWords(coord);
|
group('WhatFreeWords Tests', () {
|
||||||
print(words);
|
test('Coordinate to Words and Back', () {
|
||||||
final backToCoord = wordsToCoord(words);
|
final List<double> coord = [51.50844113, -0.116708278];
|
||||||
print(backToCoord);
|
final words = coordToWords(coord);
|
||||||
|
final backToCoord = wordsToCoord(words);
|
||||||
|
|
||||||
|
expect(backToCoord[0], closeTo(coord[0], 0.0001));
|
||||||
|
expect(backToCoord[1], closeTo(coord[1], 0.0001));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Edge Case: Maximum Latitude and Longitude', () {
|
||||||
|
final List<double> coord = [90.0, 180.0];
|
||||||
|
final words = coordToWords(coord);
|
||||||
|
final backToCoord = wordsToCoord(words);
|
||||||
|
|
||||||
|
expect(backToCoord[0], closeTo(coord[0], 0.0001));
|
||||||
|
expect(backToCoord[1], closeTo(coord[1], 0.0001));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Edge Case: Minimum Latitude and Longitude', () {
|
||||||
|
final List<double> coord = [-90.0, -180.0];
|
||||||
|
final words = coordToWords(coord);
|
||||||
|
final backToCoord = wordsToCoord(words);
|
||||||
|
|
||||||
|
expect(backToCoord[0], closeTo(coord[0], 0.0001));
|
||||||
|
expect(backToCoord[1], closeTo(coord[1], 0.0001));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Invalid Input: Out of Range Coordinates', () {
|
||||||
|
expect(() => coordToWords([100.0, 200.0]), throwsA(isA<ArgumentError>()));
|
||||||
|
expect(() => coordToWords([-100.0, -200.0]), throwsA(isA<ArgumentError>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Invalid Input: Malformed Words String', () {
|
||||||
|
expect(() => wordsToCoord("invalid.word.string"), throwsA(isA<ArgumentError>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Consistency Check: Multiple Calls Yield Same Result', () {
|
||||||
|
final List<double> coord = [34.0522, -118.2437];
|
||||||
|
final words1 = coordToWords(coord);
|
||||||
|
final words2 = coordToWords(coord);
|
||||||
|
expect(words1, equals(words2));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Inverse Mapping: Words Should Convert Back Accurately', () {
|
||||||
|
final List<double> coord = [37.7749, -122.4194];
|
||||||
|
final words = coordToWords(coord);
|
||||||
|
final backToCoord = wordsToCoord(words);
|
||||||
|
expect(backToCoord[0], closeTo(coord[0], 0.0001));
|
||||||
|
expect(backToCoord[1], closeTo(coord[1], 0.0001));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Randomized Coordinate Encoding and Decoding', () {
|
||||||
|
final Random rand = Random();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final double lat = -90 + rand.nextDouble() * 180;
|
||||||
|
final double lon = -180 + rand.nextDouble() * 360;
|
||||||
|
|
||||||
|
final words = coordToWords([lat, lon]);
|
||||||
|
final backToCoord = wordsToCoord(words);
|
||||||
|
|
||||||
|
expect(backToCoord[0], closeTo(lat, 0.0001));
|
||||||
|
expect(backToCoord[1], closeTo(lon, 0.0001));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Boundary Conditions', () {
|
||||||
|
final List<List<double>> validCoords = [
|
||||||
|
[-90.0, 0.0],
|
||||||
|
[90.0, 0.0],
|
||||||
|
[0.0, -180.0],
|
||||||
|
[0.0, 180.0]
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var coord in validCoords) {
|
||||||
|
final words = coordToWords(coord);
|
||||||
|
final backToCoord = wordsToCoord(words);
|
||||||
|
expect(backToCoord[0], closeTo(coord[0], 0.0001));
|
||||||
|
expect(backToCoord[1], closeTo(coord[1], 0.0001));
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<List<double>> invalidCoords = [
|
||||||
|
[-90.1, 0.0],
|
||||||
|
[90.1, 0.0],
|
||||||
|
[0.0, -180.1],
|
||||||
|
[0.0, 180.1]
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var coord in invalidCoords) {
|
||||||
|
expect(() => coordToWords(coord), throwsA(isA<ArgumentError>()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Minimum and Maximum Encodable Values', () {
|
||||||
|
final List<double> minCoord = [-89.9999, -179.9999];
|
||||||
|
final List<double> maxCoord = [89.9999, 179.9999];
|
||||||
|
|
||||||
|
final wordsMin = coordToWords(minCoord);
|
||||||
|
final wordsMax = coordToWords(maxCoord);
|
||||||
|
|
||||||
|
final backToCoordMin = wordsToCoord(wordsMin);
|
||||||
|
final backToCoordMax = wordsToCoord(wordsMax);
|
||||||
|
|
||||||
|
expect(backToCoordMin[0], closeTo(minCoord[0], 0.0001));
|
||||||
|
expect(backToCoordMin[1], closeTo(minCoord[1], 0.0001));
|
||||||
|
expect(backToCoordMax[0], closeTo(maxCoord[0], 0.0001));
|
||||||
|
expect(backToCoordMax[1], closeTo(maxCoord[1], 0.0001));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Invalid Word Combination', () {
|
||||||
|
expect(() => wordsToCoord("valid.valid.invalid"), throwsA(isA<ArgumentError>()));
|
||||||
|
expect(() => wordsToCoord("invalid.valid.valid"), throwsA(isA<ArgumentError>()));
|
||||||
|
expect(() => wordsToCoord("valid.invalid.valid"), throwsA(isA<ArgumentError>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
expect(backToCoord[0], closeTo(coord[0], 0.0001));
|
|
||||||
expect(backToCoord[1], closeTo(coord[1], 0.0001));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue