|
|
|
#pragma once
|
|
|
|
#include "BFileW.h"
|
|
|
|
#include "NEMO.h"
|
|
|
|
#include "HYCOM.h"
|
|
|
|
#include <utility>
|
|
|
|
#include <variant>
|
|
|
|
|
|
|
|
using michlib::BFileW;
|
|
|
|
using michlib::errmessage;
|
|
|
|
using michlib::GPL;
|
|
|
|
using michlib::message;
|
|
|
|
|
|
|
|
using DataVariants = std::variant<NEMOData,HYCOMData>;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept InfoSupported = requires(T t) {
|
|
|
|
{
|
|
|
|
t.template Info()
|
|
|
|
} -> std::convertible_to<MString>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ParametersSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) {
|
|
|
|
{
|
|
|
|
t.template Parameters(pars, args).first
|
|
|
|
} -> std::convertible_to<const BaseParameters*>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ReadPSupported = requires(T t, const BaseParameters* ip, size_t i) {
|
|
|
|
{
|
|
|
|
t.template Read(ip, i)(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
concept ReadSupported = requires(T t, size_t i) {
|
|
|
|
{
|
|
|
|
t.template Read(i)(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ActionTscSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args, const BaseParameters* ip, size_t i) {
|
|
|
|
{
|
|
|
|
t.template Parameters(pars, args).first
|
|
|
|
} -> std::convertible_to<const BaseParameters*>;
|
|
|
|
{
|
|
|
|
t.template Read(ip, i)(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Data: public DataVariants
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using TIndex = std::vector<size_t>;
|
|
|
|
|
|
|
|
private:
|
|
|
|
TIndex GetTIndexes(const MDateTime& b, const MDateTime& e) const
|
|
|
|
{
|
|
|
|
TIndex out;
|
|
|
|
auto nt = NTimes();
|
|
|
|
const MDateTime& beg = (b < e) ? b : e;
|
|
|
|
const MDateTime& end = (b > e) ? b : e;
|
|
|
|
|
|
|
|
if(beg > Time(nt - 1) || end < Time(0)) return out;
|
|
|
|
|
|
|
|
size_t ib = 0, ie = nt - 1;
|
|
|
|
for(size_t i = 0; i < nt; i++)
|
|
|
|
if(Time(i) >= beg)
|
|
|
|
{
|
|
|
|
ib = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(size_t i = nt; i != 0; i--)
|
|
|
|
if(Time(i - 1) <= end)
|
|
|
|
{
|
|
|
|
ie = i - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
out.resize(ie - ib + 1);
|
|
|
|
for(size_t i = 0; i < ie - ib + 1; i++) out[i] = i + ib;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
TIndex GetTIndexes(const MString& regex)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MDateTime time;
|
|
|
|
if(time.FromString(regex)) return TIndex(1, GetTIndex(time)); // Time, not regex
|
|
|
|
if(regex == "BEGIN" || regex == "BEG" || regex == "FIRST") return TIndex(1, 0); // First time
|
|
|
|
if(regex == "END" || regex == "LAST") return TIndex(1, NTimes() - 1); // Last time
|
|
|
|
}
|
|
|
|
|
|
|
|
TIndex out;
|
|
|
|
|
|
|
|
std::unique_ptr<regex_t> regbuf(new regex_t);
|
|
|
|
if(0 != regcomp(regbuf.get(), regex.Buf(), REG_EXTENDED | REG_NOSUB)) return out;
|
|
|
|
|
|
|
|
for(size_t i = 0; i < NTimes(); i++)
|
|
|
|
{
|
|
|
|
MString date = Time(i).ToString();
|
|
|
|
if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue;
|
|
|
|
out.push_back(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t GetTIndex(const MDateTime& t)
|
|
|
|
{
|
|
|
|
size_t nt = NTimes();
|
|
|
|
|
|
|
|
if(t <= Time(0)) return 0;
|
|
|
|
if(t >= Time(nt - 1)) return nt - 1;
|
|
|
|
for(size_t i = 0; i < nt - 1; i++)
|
|
|
|
if(t >= Time(i) && t <= Time(i + 1)) return (t - Time(i) <= Time(i + 1) - t) ? i : (i + 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
Data() = default;
|
|
|
|
|
|
|
|
Data(DataVariants&& d): DataVariants(std::move(d)) {}
|
|
|
|
|
|
|
|
MDateTime Time(size_t it) const
|
|
|
|
{
|
|
|
|
return std::visit([it = it](const auto& arg) -> auto { return arg.Time(it); }, *this);
|
|
|
|
}
|
|
|
|
size_t NTimes() const
|
|
|
|
{
|
|
|
|
return std::visit([](const auto& arg) -> auto { return arg.NTimes(); }, *this);
|
|
|
|
}
|
|
|
|
|
|
|
|
MString Init(const CLArgs& args)
|
|
|
|
{
|
|
|
|
MString src = args.contains("source") ? args.at("source") : "";
|
|
|
|
if(!src.Exist()) return "No source specified";
|
|
|
|
if(src == "NEMO")
|
|
|
|
{
|
|
|
|
NEMOData data;
|
|
|
|
auto res = data.Open(args);
|
|
|
|
if(res.Exist()) return "Can't open source " + src + ":\n" + res;
|
|
|
|
*this = Data(std::move(data));
|
|
|
|
}
|
|
|
|
else if(src == "HYCOM")
|
|
|
|
{
|
|
|
|
HYCOMData data;
|
|
|
|
auto res = data.Open(args);
|
|
|
|
if(res.Exist()) return "Can't open source " + src + ":\n" + res;
|
|
|
|
*this = Data(std::move(data));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return "Unknown source: " + src;
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
MString ActionInfo(const CLArgs& args);
|
|
|
|
MString ActionTsc(const CLArgs& args);
|
|
|
|
};
|