meos-2024/code/oFreeImport.h
erikmelin a13eef041a MeOS version 3.5.785.
Use AGPL instead of GPL
2017-08-30 13:31:32 +02:00

256 lines
7.5 KiB
C++

#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include <set>
#include <map>
#include <vector>
#include <string>
#include "oEvent.h"
class oWordDatabase;
typedef oWordDatabase* pWordDatabase;
typedef map<wchar_t, pWordDatabase> MapTable;
const wchar_t indexMapStart='a';
const wchar_t indexMapEnd='z';
const int hashSplitSize=16;
const int hashTableSize=indexMapEnd-indexMapStart+1;
class oFreeImport;
class oWordDatabase {
public:
virtual char getType() const = 0;
virtual const char *deserialize(const char *bf, const char *end) = 0;
virtual char *serialize(char *bf) const = 0;
virtual int serialSize() const = 0;
virtual pWordDatabase split() {return this;}
virtual void insert(const wchar_t *s) = 0;
virtual bool lookup(const wchar_t *s) const = 0;
virtual ~oWordDatabase() = 0 {}
};
class oWordDB : public oWordDatabase {
protected:
char getType() const {return 1;}
set<wstring> str;
public:
const char *deserialize(const char *bf, const char *end);
char *serialize(char *bf) const;
int serialSize() const;
pWordDatabase split();
void insert(const wchar_t *s);
bool lookup(const wchar_t *s) const;
size_t size();
};
class oWordIndexHash : public oWordDatabase {
protected:
char getType() const {return 2;}
pWordDatabase hashTable[hashTableSize];
MapTable unMapped;
bool hashAll;
public:
const char *deserialize(const char *bf, const char *end);
char *serialize(char *bf) const;
int serialSize() const;
void insert(const wchar_t *s);
bool lookup(const wchar_t *s) const;
void clear();
~oWordIndexHash();
oWordIndexHash(bool hashAll_);
};
class oWordList {
protected:
oWordIndexHash wh;
public:
void serialize(vector<char> &serial) const;
void deserialize(const vector<char> &serial);
void save(const wstring &file) const;
void load(const wstring &file);
void insert(const wchar_t *s);
bool lookup(const wchar_t *s) const;
~oWordList();
oWordList();
};
struct oEntryPerson {
wstring name1;
wstring name2;
wstring club;
int cardNo;
void swap();
int nameCount() const;
oEntryPerson(const wstring &clb);
};
struct oEntryBlock {
// Remember clear for additional data
vector<oEntryPerson> ePersons;
wstring eClub;
wstring eClass;
bool isClassSet;
wstring eStartTime;
bool canInsertName;
int nClubsSet;
const oFreeImport &freeImporter;
int nameCount();
void setClub(const wchar_t *s);
void setClass(const wchar_t *s);
void setCardNo(int c);
void setStartTime(const wchar_t *s);
void addPerson(const wchar_t *s, bool complete);
vector<wstring> getPersons() const;
void clear(const wstring &rulingClub, const wstring &rulingClass);
// Return true if more clubs can be accepted
bool acceptMoreClubs(int expectedNumRunners) const;
bool expectMoreNames(int expectedNumRunners) const;
bool needCard() const;
bool hasClub() const {return !eClub.empty();}
/** Return true if class explicitly set. May have a ruling class anyway*/
bool hasClass() const {return isClassSet;}
bool hasStartTime() const {return !eStartTime.empty();}
bool hasName() {return !ePersons.empty() &&
!ePersons.front().name1.empty();}
void cleanEntry(); //Remove bad data.
oEntryBlock(const oFreeImport &importer);
oEntryBlock(const oEntryBlock &eb);
void operator=(const oEntryBlock &eb);
int getNumPersons() const {return ePersons.size();}
wstring getTeamName() const;
wstring getName(int k) const;
wstring getClub(int k) const;
int getCard(int k) const;
/** Make name complete */
void completeName();
};
struct MatchPattern {
short nName;
short singleName;
short nClass;
short nClub;
short nTime;
short nCard;
bool isClass(int level=2) const {return nClass>(nClub+nTime+nCard)+level;}
bool isClub(int level=2) const {return nClub>(nClass+nTime+nCard)+level;}
bool isTime(int level=2) const {return nTime>(nClass+nClub+nCard)+level;}
bool isCard(int level=2) const {return nCard>(nClass+nTime+nTime)+level;}
bool isName(int level=2) const {return nName>(nCard+nClass+nTime+nClub)+level;}
bool isCompleteName() const {return singleName<int(nName*0.8);}
MatchPattern():nClass(0), nClub(0), nTime(0),
nCard(0), nName(0), singleName(0) {}
};
class oFreeImport {
protected:
set<int> separator;
oWordList givenDB;
oWordList familyDB;
oWordList clubDB;
oWordList classDB;
enum Types {
None = -2,
Unknown = -1,
Club = 0,
Class = 1,
Time = 2,
Card = 3,
Name = 4
};
void analyzePart(wchar_t *part, const MatchPattern &ptrn, int nNamesPerPart,
oEntryBlock &entry, vector<oEntryBlock> &entries, bool allowNames);
//bool analyze(vector<bool> &b, int &offset, int &delta) const;
wchar_t *extractWord(wchar_t *&str, int &count) const;
wchar_t *extractPart(wchar_t *&str, int &wordCount) const;
wchar_t *extractLine(wchar_t *&str, int &count) const;
bool isNumber(const wchar_t *str, int &number) const;
bool isTime(const wstring &m) const;
bool isName(const wchar_t *p) const;
bool isCard(const wchar_t *p) const;
bool isCrap(const wchar_t *p) const;
bool loaded;
int preAnalyzeRow(vector<wchar_t *> &p,
const vector<MatchPattern> &ptrn,
vector<int> &classified);
// Runners per class in defined classes
map<wstring, int> runnersPerClass;
/** Must not return 0 */
int getExpectedNumRunners(const wstring &cls) const;
friend struct oEntryBlock;
/** Check if a line is a header and remove header words,
name: , class: etc. Returns true if the entire line
is header (->ignore) */
bool analyzeHeaders(vector<wchar_t *> &line) const;
/** Returns true if the given word is a header word */
bool isHeaderWord(const wstring &word) const;
mutable set<wstring> headerWords;
// Expected club for all entries
wstring rulingClub;
wstring rulingClass;
Types lastInsertedType;
public:
void load();
bool isLoaded() const {return loaded;}
void save() const;
void init(const oRunnerList &r, const oClubList &clb, const oClassList &cls);
void buildDatabases(oEvent &oe);
void extractEntries(wchar_t *bf, vector<oEntryBlock> &entries);
void showEntries(gdioutput &gdi, const vector<oEntryBlock> &entries);
void addEntries(pEvent oe, const vector<oEntryBlock> &entries);
void test(const oRunnerList &li);
oFreeImport(void);
~oFreeImport(void);
friend class oEvent;
};