swift
aircraftcategorylist.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2019 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QJsonValue>
7 #include <QMap>
8 #include <Qt>
9 
10 #include "misc/setbuilder.h"
11 
12 SWIFT_DEFINE_SEQUENCE_MIXINS(swift::misc::aviation, CAircraftCategory, CAircraftCategoryList)
13 
14 namespace swift::misc::aviation
15 {
17 
20  {}
21 
22  CAircraftCategoryList CAircraftCategoryList::findByName(const QString &name, Qt::CaseSensitivity cs) const
23  {
24  return this->findBy([&](const CAircraftCategory &category) { return category.matchesName(name, cs); });
25  }
26 
28 
30  {
31  this->sort([](const CAircraftCategory &a, const CAircraftCategory &b) {
32  const int c = a.compareByLevel(b);
33  return c < 0;
34  });
35  }
36 
38  {
39  CSetBuilder<QString> levels;
40  for (const CAircraftCategory &category : *this) { levels.insert(category.getLevelString()); }
41  return levels;
42  }
43 
44  QString CAircraftCategoryList::getLevelsString(const QString &separator) const
45  {
46  const QSet<QString> levels = this->getLevelStrings();
47  if (levels.isEmpty()) { return {}; }
48  return levels.values().join(separator);
49  }
50 
52  {
53  CSetBuilder<int> levels;
54  for (const CAircraftCategory &category : *this) { levels.insert(category.getFirstLevel()); }
55  QList<int> ll = levels;
56  ll.removeOne(0);
57  return ll;
58  }
59 
61  {
62  CSetBuilder<int> levels;
63  for (const CAircraftCategory &category : *this) { levels.insert(category.getSecondLevel()); }
64  QList<int> ll = levels;
65  ll.removeOne(0);
66  return ll;
67  }
68 
70  {
71  if (categories.isEmpty()) { return CAircraftCategoryList(); }
72  QMap<int, CAircraftCategory> highestLevels;
73  for (const CAircraftCategory &category : *this)
74  {
75  const int fl = category.getFirstLevel();
76  if (highestLevels.contains(fl))
77  {
78  if (highestLevels[fl].isHigherLevel(category)) { highestLevels[fl] = category; }
79  }
80  else { highestLevels[fl] = category; }
81  }
82 
83  CAircraftCategoryList topLevels;
84  for (const CAircraftCategory &category : highestLevels.values()) { topLevels.push_back(category); }
85  return topLevels;
86  }
87 
89  {
90  CAircraftCategoryList categories;
91  for (const CAircraftCategory &category : *this)
92  {
93  if (category.getFirstLevel() == level) { categories.push_back(category); }
94  }
95  return categories;
96  }
97 
98  CAircraftCategoryList CAircraftCategoryList::findByLevel(const QList<int> &level, bool noRootNode) const
99  {
100  CAircraftCategoryList categories;
101  if (level.isEmpty()) { return categories; }
102  const int ls = level.size();
103  for (const CAircraftCategory &category : *this)
104  {
105  if (noRootNode && ls == category.getDepth()) { continue; } // ignore root nodes
106  if (category.matchesLevel(level)) { categories.push_back(category); }
107  }
108  return categories;
109  }
110 
112  {
113  if (level.size() != 3) { return {}; }
114  for (const CAircraftCategory &category : *this)
115  {
116  if (category.isLevel(level[0], level[1], level[2])) { return category; }
117  }
118  return {};
119  }
120 
122  {
123  return this->findBy(&CAircraftCategory::isFirstLevel, true);
124  }
125 
127  {
128  QList<int> levels = category.getLevel();
129  CAircraftCategoryList categories;
130  if (levels.size() < 2) { categories = this->findFirstLevels(); }
131  else
132  {
133  levels.removeLast();
134  categories = this->findByLevel(levels, true);
135  }
136  categories.remove(category);
137  return categories;
138  }
139 
141  {
142  if (category.isNull() || this->isEmpty()) { return {}; }
143  if (category.isFirstLevel()) { return {}; }
144  const bool isL2 = category.getDepth() == 2;
145  const QList<int> loopLevels = isL2 ? this->getFirstLevels() : this->getSecondLevels();
146  if (loopLevels.isEmpty()) { return {}; }
147 
148  QList<int> level = category.getLevel();
149  CAircraftCategoryList result;
150  for (int l = loopLevels.front(); loopLevels.back() >= l; ++l)
151  {
152  level[isL2 ? 0 : 1] = l;
153  if (category.isLevel(level)) { continue; } // ignore category itself
154  const CAircraftCategory cat = this->findByFullLevel(level);
155  if (!cat.isNull()) { result.push_back(cat); }
156  }
157  return result;
158  }
159 
160  int CAircraftCategoryList::removeIfLevel(const QList<int> &level)
161  {
162  if (level.isEmpty()) { return 0; }
163  const int c = this->size();
164  const CAircraftCategoryList removed = this->removedLevel(level);
165  const int delta = c - removed.size();
166  if (delta > 0) { *this = removed; }
167  return delta;
168  }
169 
171  {
172  if (level.isEmpty()) { return *this; } // nothing removed
173  CAircraftCategoryList removed;
174  for (const CAircraftCategory &category : *this)
175  {
176  if (category.matchesLevel(level)) { continue; }
177  removed.push_back(category);
178  }
179  return removed;
180  }
181 
183  {
184  CAircraftCategoryList categories;
185  for (const QJsonValue &value : array)
186  {
187  const CAircraftCategory category(CAircraftCategory::fromDatabaseJson(value.toObject()));
188  categories.push_back(category);
189  }
190  return categories;
191  }
192 
193 } // namespace swift::misc::aviation
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
void sortBy(K1 key1, Keys... keys)
In-place sort by some particular key(s).
Definition: sequence.h:576
CSequence findBy(Predicate p) const
Return a copy containing only those elements for which a given predicate returns true.
Definition: sequence.h:398
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition: sequence.h:305
int remove(const T &object)
Remove all elements equal to the given object, if it is contained.
Definition: sequence.h:435
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
void sort(Predicate p)
In-place sort by a given comparator predicate.
Definition: sequence.h:560
Build a QSet more efficiently when calling insert() in a for loop.
Definition: setbuilder.h:25
void insert(const T &value)
Add an element to the set. Runs in amortized constant time.
Definition: setbuilder.h:29
Value object for aircraft categories.
const QString & getPath() const
Path.
int compareByLevel(const CAircraftCategory &other) const
Level compare.
bool isLevel(int l1, int l2, int l3) const
Is that given level?
QString getLevelString() const
Level string.
bool matchesName(const QString &name, Qt::CaseSensitivity cs) const
Matching name?
QList< int > getLevel() const
Levels depending on depth, 3.2 -> 3,2 / 1.0 -> 1 / 4.3.1 -> 4,3,1.
static CAircraftCategory fromDatabaseJson(const QJsonObject &json, const QString &prefix=QString())
From our database JSON format.
bool matchesLevel(int l1, int l2=0, int l3=0) const
Is matching the level, 0 ignored.
Value object encapsulating a list of ICAO codes.
CAircraftCategoryList findByLevel(const QList< int > &level, bool noRootNode=false) const
Find by levels.
QList< int > getFirstLevels() const
All levels sorted.
QString getLevelsString(const QString &separator=", ") const
Get all level strings.
int removeIfLevel(const QList< int > &level)
Remove by level.
CAircraftCategoryList findInParallelBranch(const CAircraftCategory &category) const
Find siblings.
CAircraftCategoryList findByFirstLevel(int level) const
Find by first level.
CAircraftCategoryList findFirstLevels() const
Find first levels.
static CAircraftCategoryList fromDatabaseJson(const QJsonArray &array)
From our database JSON format.
CAircraftCategoryList findByName(const QString &name, Qt::CaseSensitivity cs=Qt::CaseInsensitive) const
Find by name.
CAircraftCategory findByFullLevel(const QList< int > &level) const
Find by exact levels.
QList< int > getSecondLevels() const
All levels sorted.
QSet< QString > getLevelStrings() const
Get all level strings.
CAircraftCategoryList removedLevel(const QList< int > &level) const
With removed categories.
CAircraftCategoryList findHighestLevels(const CAircraftCategoryList &categories)
Find highest (top) level of categories.
CAircraftCategoryList findSiblings(const CAircraftCategory &category) const
Find siblings.
#define SWIFT_DEFINE_SEQUENCE_MIXINS(Namespace, T, List)
Explicit template definition of mixins for a CSequence subclass.
Definition: sequence.h:63