You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.4 KiB

#pragma once
#include "AVISO.h"
#include "AVISOLOCAL.h"
2 years ago
#include "BFileW.h"
#include "HYCOM.h"
#include "NEMO.h"
#include <utility>
#include <variant>
2 years ago
using michlib::BFileW;
using michlib::errmessage;
using michlib::GPL;
using michlib::message;
using DataVariants = std::variant<NEMOData, HYCOMData, AVISOData, AVISOLOCALData>;
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 MString& vname, const BaseParameters* ip, size_t i) {
{
t.template Read(vname, ip, i)(0)
} -> std::convertible_to<real>;
};
template<class T>
concept ReadSupported = requires(T t, const MString& vname, size_t i) {
{
t.template Read(vname, i)(0)
} -> std::convertible_to<real>;
};
template<class T>
concept ReadUVPSupported = requires(T t, const BaseParameters* ip, size_t i) {
{
t.template ReadUV(ip, i).U(0, 0) + t.template ReadUV(ip, i).V(0, 0)
} -> std::convertible_to<real>;
};
2 years ago
class Data: public DataVariants
{
public:
using TIndex = std::vector<size_t>;
private:
TIndex GetTIndexes(const MDateTime& b, const MDateTime& e) const
2 years ago
{
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++)
2 years ago
{
MString date = Time(i).ToString();
if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue;
out.push_back(i);
2 years ago
}
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;
2 years ago
}
public:
Data() = default;
Data(DataVariants&& d): DataVariants(std::move(d)) {}
MDateTime Time(size_t it) const
2 years ago
{
return std::visit([it = it](const auto& arg) -> auto { return arg.Time(it); }, *this);
2 years ago
}
size_t NTimes() const
2 years ago
{
return std::visit([](const auto& arg) -> auto { return arg.NTimes(); }, *this);
2 years ago
}
2 years ago
auto CheckVar(const MString& vname) const
{
return std::visit([&vname = std::as_const(vname)](const auto& arg) -> auto { return arg.CheckVar(vname); }, *this);
}
MString Init(const CLArgs& args)
2 years ago
{
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 == "AVISO")
{
AVISOData 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 == "AVISOLOCAL")
{
AVISOLOCALData 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 "";
2 years ago
}
MString ActionInfo(const CLArgs& args);
MString ActionTsc(const CLArgs& args);
MString ActionUV(const CLArgs& args);
};