Graphs_dart/bin/src/graph.dart
2021-10-25 02:17:56 +04:00

334 lines
8.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
class Separators {
final String dotToConnections = ": ";
final String dotToLength = "|";
final String space = " ";
final String hasLength = "Взвешенный\n";
final String hasNoLength = "НеВзвешенный\n";
final String isOriented = "Ориентированный\n";
final String isNotOriented = "НеОриентированный\n";
final String nL = "\n";
final String end = "END";
Separators();
}
class Dot {
//Data
// ignore: prefer_final_fields
String _name = "";
int num = -1;
Map<int, int> ln = <int, int>{};
//****Get****
String getName() => _name;
bool hasConnection(int n) => ln.containsKey(n);
int getLength(int x) {
if (hasConnection(x)) {
return ln[x]!;
}
return -1;
}
//****Get****
//Set
void setName(String n) => _name = n;
//Add
void addPath(int inp, int length) =>
ln[inp] = length; // нужна проверка на ориентированность
//Del
void delPath(int n) => ln.removeWhere((key, value) =>
key == n); // удалить обратный путь если не ориентированный
//Print
void printD() {
stdout.write("$_name: №$num => ");
for (var i in ln.keys) {
stdout.write("$i|${ln[i]} ");
}
stdout.write("\n");
}
//******Constructor******
Dot() {
_name = "Undefined";
num = -1;
ln = <int, int>{};
}
Dot.fromTwoLists(String name, List<int> num0, List<int> length,
[int n = -1]) {
_name = name;
num = n;
Map<int, int> nw = <int, int>{};
if (num0.length != length.length) {
print("Error in lists");
} else {
for (var i = 0; i < num0.length; i++) {
nw[num0[i]] = length[i];
ln = nw;
}
}
}
Dot.fromMap(String name, Map<int, int> l, [int n = -1]) {
_name = name;
num = n;
ln = l;
}
//******Constructor******
//Copy
Dot.clone(Dot a) {
_name = a.getName();
num = a.num;
ln = a.ln;
}
}
class Graphs {
//Data
String _name = "Undefined"; //Имя
int _amount = 0; //Количество вершин
List<Dot> _dots = <Dot>[]; //Список смежности вершин
// ignore: prefer_final_fields
Map<int, String> _nameTable = <int, String>{}; //Список вершин по именам
bool _useLength = false; //Взвешенность
// ignore: prefer_final_fields
bool _oriented = false; //Ориентированность
//*********************Add************************
bool addDot(Dot a) {
if (getNumByName(a.getName()) != null) {
print(
"Dot name ${a.getName()} already in use. Change name or use addPath");
return false;
}
_amount++;
a.num = _amount;
_dots.add(a);
_syncNameTable();
checkDots(false);
if (!_oriented) _fullFix();
return true;
}
bool addDotFromToLists(String name, List<int> num0, List<int> length,
[int n = -1]) {
var a = Dot.fromTwoLists(name, num0, length, n);
if (getNumByName(a.getName()) != null) {
print(
"Dot name ${a.getName()} already in use. Change name or use addPath");
return false;
}
_amount++;
a.num = _amount;
_dots.add(a);
_syncNameTable();
checkDots(false);
if (!_oriented) _fixPathAfterInsert(a);
return true;
}
bool addIsolated(String name) {
var o = addDot(Dot.fromTwoLists(name, [], []));
_syncNameTable();
return o;
}
bool addPath(int from, int to, [int len = 0]) {
if (from <= 0 || from > _amount || to <= 0 && to > _amount) {
return false;
}
_dots[from - 1].addPath(to, len);
if (!_oriented) {
_dots[to - 1].addPath(from, len);
}
return true;
}
//*********************Add************************
//******Helper*******
bool checkDots([bool verbose = false]) {
for (var a in _dots) {
for (var i in a.ln.keys) {
try {
if (!_dots[i - 1].ln.containsKey(a.num)) {
if (verbose) print("Can't find ${a.num}");
return false;
}
} catch (e) {
if (verbose) {
print("Can't find Dot $i for path ${a.num}->$i. Exception $e");
}
_dots[a.num - 1].ln.remove(i);
return false;
}
}
}
return true;
}
void _fixPathAfterInsert(Dot a) {
//Для неориентированного
for (var i in a.ln.keys) {
if (!_dots[i - 1].ln.containsKey(a.num)) {
_dots[i - 1].addPath(i, a.ln[i]!);
}
}
}
void _fullFix() {
for (var i in _dots) {
_fixPathAfterInsert(i);
}
}
void _syncNameTable() {
_nameTable = <int, String>{};
for (var i in _dots) {
_nameTable[i.num] = i.getName();
}
}
void _syncNum() {
_amount = 0;
for (var i in _dots) {
i.num = ++_amount;
}
_syncNameTable();
}
//******Helper*******
//*****Getters*******
bool getDoubleSided() => _oriented;
bool getUseLength() => _useLength;
List<Dot> getDots() => _dots;
String getName() => _name;
String? getNameByNum(int n) => _nameTable[n];
int? getNumByName(String n) {
for (var i in _nameTable.keys) {
if (_nameTable[i] == n) return i;
}
return null;
}
List<List<int>>? getTable() {
List<List<int>>? out = <List<int>>[];
for (int i = 0; i < _amount; i++) {
List<int> xx = <int>[];
for (int j = 1; j <= _amount; j++) {
xx.add(_dots[i].getLength(j));
}
out.add(xx);
}
return out;
}
//*****Getters*******
//******Print******
void printG() {
stdout.write("$_name: ");
if (_oriented) {
stdout.write("Ориентированный, ");
} else {
stdout.write("Не ориентированный, ");
}
if (_useLength) {
print("Взвешенный");
} else {
print("Не взвешенный");
}
for (var i in _dots) {
i.printD();
}
}
void toFile(String name) {
Separators sep = Separators();
var file = File(name);
file.writeAsStringSync("$_name\n");
if (_oriented) {
file.writeAsStringSync(sep.isOriented, mode: FileMode.append);
} else {
file.writeAsStringSync(sep.isNotOriented, mode: FileMode.append);
}
if (_useLength) {
file.writeAsStringSync(sep.hasLength, mode: FileMode.append);
} else {
file.writeAsStringSync(sep.hasNoLength, mode: FileMode.append);
}
for (int i = 0; i < _amount; i++) {
file.writeAsStringSync((i + 1).toString() + sep.dotToConnections,
mode: FileMode.append);
var d = _dots[i].ln;
for (var j in d.keys) {
file.writeAsStringSync(
j.toString() + sep.dotToLength + d[j].toString() + " ",
mode: FileMode.append);
}
file.writeAsStringSync(sep.nL, mode: FileMode.append);
}
file.writeAsStringSync(sep.end, mode: FileMode.append);
}
//******Print******
//*******Constructor********
Graphs() {
_name = "Udefined";
_dots = <Dot>[];
_useLength = false;
_oriented = false;
_amount = 0;
_nameTable = <int, String>{};
}
Graphs.fromList(String n, List<Dot> d, bool useL, bool oriented) {
_name = n;
_dots = d;
_useLength = useL;
_amount = _dots.length;
_oriented = oriented;
_syncNum();
if (!_oriented) _fullFix();
}
Graphs.fromFile(String path) {
Separators sep = Separators();
File file = File(path);
List<String> lines = file.readAsLinesSync();
_name = lines.removeAt(0);
_oriented = lines.removeAt(0) == sep.isOriented;
_useLength = lines.removeAt(0) == sep.hasLength;
_dots = <Dot>[];
for (var l in lines) {
if (l != sep.end) {
var spl = l.split(sep.space);
List<int> dot = <int>[];
List<int> len = <int>[];
String name = spl.removeAt(0);
name = name.substring(0, name.length - 1);
for (var splitted in spl) {
var dt = splitted.split(sep.dotToLength);
dot.add(int.parse(dt[0]));
len.add(int.parse(dt[1]));
}
Dot add = Dot.fromTwoLists(name, dot, len);
_dots.add(add);
}
}
_syncNameTable();
if (!_oriented) _fullFix();
}
//*******Constructor********
//Copy
Graphs.clone(Graphs a) {
_name = a.getName();
_dots = a.getDots();
_oriented = a.getDoubleSided();
_useLength = a.getUseLength();
_amount = _dots.length;
_syncNameTable();
}
}