From: 石博文 Date: Tue, 16 Jan 2018 05:01:37 +0000 (+0800) Subject: Add a mathmatic unit conver tools to format numbers. X-Git-Tag: archive/raspbian/5.7.12-2+rpi1^2~130^2~20 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=198b958acfda100a7d824cb9bacc80cbd7b3103d;p=dtkcore.git Add a mathmatic unit conver tools to format numbers. Change-Id: Ie01377598ec64efb64a3a7df7df7ac0615020ac4 --- diff --git a/src/util/DAbstractUnitFormatter b/src/util/DAbstractUnitFormatter new file mode 100644 index 0000000..2d494ea --- /dev/null +++ b/src/util/DAbstractUnitFormatter @@ -0,0 +1 @@ +#include "dabstractunitformatter.h" diff --git a/src/util/DDiskSizeFormatter b/src/util/DDiskSizeFormatter new file mode 100644 index 0000000..6584e09 --- /dev/null +++ b/src/util/DDiskSizeFormatter @@ -0,0 +1 @@ +#include "ddisksizeformatter.h" diff --git a/src/util/DTimeUnitFormatter b/src/util/DTimeUnitFormatter new file mode 100644 index 0000000..07d52a6 --- /dev/null +++ b/src/util/DTimeUnitFormatter @@ -0,0 +1 @@ +#include "dtimeunitformatter.h" diff --git a/src/util/dabstractunitformatter.cpp b/src/util/dabstractunitformatter.cpp new file mode 100644 index 0000000..418ed31 --- /dev/null +++ b/src/util/dabstractunitformatter.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * 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 + * 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 . + */ + +#include "dabstractunitformatter.h" + +DCORE_BEGIN_NAMESPACE + +DAbstractUnitFormatter::DAbstractUnitFormatter() +{ + +} + +DAbstractUnitFormatter::~DAbstractUnitFormatter() +{ + +} + +qreal DAbstractUnitFormatter::formatAs(qreal value, int currentUnit, const int targetUnit) const +{ + while (currentUnit < targetUnit) + value /= unitConvertRate(currentUnit++); + while (currentUnit > targetUnit) + value *= unitConvertRate(--currentUnit); + + return value; +} + +QPair DAbstractUnitFormatter::format(const qreal value, const int unit) const +{ + // can convert to smaller unit + if (unit > unitMin() && value < unitValueMin(unit)) + return format(value * unitConvertRate(unit - 1), unit - 1); + + // can convert to bigger unit + if (unit < unitMax() && value > unitValueMax(unit)) + return format(value / unitConvertRate(unit), unit + 1); + + return QPair(value, unit); +} + +QList > DAbstractUnitFormatter::formatAsUnitList(const qreal value, int unit) const +{ + if (qFuzzyIsNull(value)) + return QList>(); + + if (value < unitValueMin(unit) || unit == unitMin()) + { + if (unit != unitMin()) + return formatAsUnitList(value * unitConvertRate(unit - 1), unit - 1); + else + return std::move(QList>() << QPair(value, unit)); + } + + ulong _value = ulong(value); + QList> ret = formatAsUnitList(value - _value, unit); + + while (_value && unit != unitMax()) + { + const ulong rate = unitConvertRate(unit); + const ulong r = _value % rate; + if (r) + ret.push_front(QPair(r, unit)); + + unit += 1; + _value /= rate; + } + + if (_value) + ret.push_front(QPair(_value, unit)); + + return ret; +} + +DCORE_END_NAMESPACE diff --git a/src/util/dabstractunitformatter.h b/src/util/dabstractunitformatter.h new file mode 100644 index 0000000..395cb0a --- /dev/null +++ b/src/util/dabstractunitformatter.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * 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 + * 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 . + */ + +#ifndef DABSTRACTUNITFORMATTER_H +#define DABSTRACTUNITFORMATTER_H + +#include "dtkcore_global.h" + +#include +#include + +DCORE_BEGIN_NAMESPACE + +class DAbstractUnitFormatter +{ +public: + DAbstractUnitFormatter(); + ~DAbstractUnitFormatter(); + +protected: + virtual int unitMax() const = 0; + virtual int unitMin() const = 0; + virtual uint unitConvertRate(int unitId) const = 0; + virtual qreal unitValueMax(int unitId) const { return unitConvertRate(unitId) - 1; } + virtual qreal unitValueMin(int unitId) const { Q_UNUSED(unitId); return 1; } + virtual QString unitStr(int unitId) const = 0; + +public: + qreal formatAs(qreal value, int currentUnit, const int targetUnit) const; + QPair format(const qreal value, const int unit) const; + QList> formatAsUnitList(const qreal value, int unit) const; +}; + +DCORE_END_NAMESPACE + +#endif // DABSTRACTUNITFORMATTER_H diff --git a/src/util/ddisksizeformatter.cpp b/src/util/ddisksizeformatter.cpp new file mode 100644 index 0000000..fbd9806 --- /dev/null +++ b/src/util/ddisksizeformatter.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * 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 + * 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 . + */ + +#include "ddisksizeformatter.h" + +#include + +DCORE_BEGIN_NAMESPACE + +DDiskSizeFormatter::DDiskSizeFormatter() + : DAbstractUnitFormatter() +{ + +} + +QString DDiskSizeFormatter::unitStr(int unitId) const +{ + switch (unitId) + { + case B: return QStringLiteral("B"); + case K: return QStringLiteral("KB"); + case M: return QStringLiteral("MB"); + case G: return QStringLiteral("GB"); + case T: return QStringLiteral("TB"); + } + + return QString(); +} + +DDiskSizeFormatter DDiskSizeFormatter::rate(int rate) +{ + m_rate = rate; + + return *this; +} + +DCORE_END_NAMESPACE diff --git a/src/util/ddisksizeformatter.h b/src/util/ddisksizeformatter.h new file mode 100644 index 0000000..de7d7d7 --- /dev/null +++ b/src/util/ddisksizeformatter.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * 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 + * 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 . + */ + +#ifndef DISKSIZEFORMATTER_H +#define DISKSIZEFORMATTER_H + +#include "dabstractunitformatter.h" + +DCORE_BEGIN_NAMESPACE + +class DDiskSizeFormatter : public DAbstractUnitFormatter +{ +public: + DDiskSizeFormatter(); + + enum DiskUnits + { + B, + K, + M, + G, + T, + }; + + QString unitStr(int unitId) const override; + + DDiskSizeFormatter rate(int rate); + +protected: + int unitMin() const override { return B; } + int unitMax() const override { return T; } + uint unitConvertRate(int unitId) const override { Q_UNUSED(unitId); return m_rate; } + +private: + int m_rate = 1000; +}; + +DCORE_END_NAMESPACE + +#endif // DISKSIZEFORMATTER_H diff --git a/src/util/dtimeunitformatter.cpp b/src/util/dtimeunitformatter.cpp new file mode 100644 index 0000000..79cc831 --- /dev/null +++ b/src/util/dtimeunitformatter.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * 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 + * 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 . + */ + +#include "dtimeunitformatter.h" + +#include + +DCORE_BEGIN_NAMESPACE + +DTimeUnitFormatter::DTimeUnitFormatter() + : DAbstractUnitFormatter() +{ + +} + +uint DTimeUnitFormatter::unitConvertRate(int unitId) const +{ + switch (unitId) + { + case Seconds: return 60; + case Minute: return 60; + case Hour: return 24; + default:; + } + + return 0; +} + +QString DTimeUnitFormatter::unitStr(int unitId) const +{ + switch (unitId) + { + case Seconds: return QStringLiteral("s"); + case Minute: return QStringLiteral("m"); + case Hour: return QStringLiteral("h"); + case Day: return QStringLiteral("d"); + default:; + } + + return QString(); +} + +DCORE_END_NAMESPACE diff --git a/src/util/dtimeunitformatter.h b/src/util/dtimeunitformatter.h new file mode 100644 index 0000000..3c71bb8 --- /dev/null +++ b/src/util/dtimeunitformatter.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. + * + * 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 + * 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 . + */ + +#ifndef DTIMEUNITFORMATTER_H +#define DTIMEUNITFORMATTER_H + +#include "dabstractunitformatter.h" + +DCORE_BEGIN_NAMESPACE + +class DTimeUnitFormatter : public DAbstractUnitFormatter +{ +public: + DTimeUnitFormatter(); + + enum TimeUnits + { + Seconds, + Minute, + Hour, + Day, + }; + + QString unitStr(int unitId) const override; + +protected: + int unitMax() const override { return Day; } + int unitMin() const override { return Seconds; } + uint unitConvertRate(int unitId) const override; +}; + +DCORE_END_NAMESPACE + +#endif // DTIMEUNITFORMATTER_H diff --git a/src/util/util.pri b/src/util/util.pri index eee15ce..60eaaa1 100644 --- a/src/util/util.pri +++ b/src/util/util.pri @@ -1,6 +1,9 @@ HEADERS += \ $$PWD/dutil.h \ - $$PWD/dpinyin.h + $$PWD/dpinyin.h \ + $$PWD/dtimeunitformatter.h \ + $$PWD/dabstractunitformatter.h \ + $$PWD/ddisksizeformatter.h includes.files += $$PWD/*.h includes.files += \ @@ -9,3 +12,8 @@ includes.files += \ RESOURCES += \ $$PWD/util.qrc + +SOURCES += \ + $$PWD/dtimeunitformatter.cpp \ + $$PWD/dabstractunitformatter.cpp \ + $$PWD/ddisksizeformatter.cpp diff --git a/tests/dutiltester.cpp b/tests/dutiltester.cpp index a4fce03..0cff403 100644 --- a/tests/dutiltester.cpp +++ b/tests/dutiltester.cpp @@ -25,6 +25,8 @@ #include "log/LogManager.h" #include "filesystem/dpathbuf.h" #include "singletontester.h" +#include "util/dtimeunitformatter.h" +#include "util/ddisksizeformatter.h" DCORE_USE_NAMESPACE @@ -76,3 +78,79 @@ void TestDUtil::testDSingleton() QThread::sleep(5); } +void TestDUtil::testTimeFormatter() +{ + const DTimeUnitFormatter timeFormatter; + + // 3600 seconds == 1 hour + const auto r0 = timeFormatter.format(3600, DTimeUnitFormatter::Seconds); + Q_ASSERT(r0.first == 1 && r0.second == DTimeUnitFormatter::Hour); + + // 86400 seconds == 1 day + const auto r1 = timeFormatter.format(86400, DTimeUnitFormatter::Seconds); + Q_ASSERT(r1.first == 1 && r1.second == DTimeUnitFormatter::Day); + + // 129600 seconds == 1.5 day + const auto r3 = timeFormatter.format(129600, DTimeUnitFormatter::Seconds); + Q_ASSERT(qFuzzyCompare(1.5, r3.first) && r3.second == DTimeUnitFormatter::Day); + + // 1.5 day == 36 hours + const auto r4 = timeFormatter.formatAs(1.5, DTimeUnitFormatter::Day, DTimeUnitFormatter::Hour); + Q_ASSERT(r4 == 36); +} + +void TestDUtil::testTimeFormatterList() +{ + const DTimeUnitFormatter timeFormatter; + + // 135120.5 Minutes == 93 days + 20 hours + 30 seconds + const auto r = timeFormatter.formatAsUnitList(135120.5, DTimeUnitFormatter::Minute); + Q_ASSERT(r[0].first == 93 && r[0].second == DTimeUnitFormatter::Day); + Q_ASSERT(r[1].first == 20 && r[1].second == DTimeUnitFormatter::Hour); + Q_ASSERT(r[2].first == 30 && r[2].second == DTimeUnitFormatter::Seconds); +} + +void TestDUtil::testDiskFormatter() +{ + const DDiskSizeFormatter diskFormatter1000 = DDiskSizeFormatter(); + + // 1000 K == 1 M + const auto i0 = diskFormatter1000.format(1000, DDiskSizeFormatter::K); + Q_ASSERT(i0.first == 1 && i0.second == DDiskSizeFormatter::M); + + // 1000 K == 1000000 B + const auto i1 = diskFormatter1000.formatAs(1000, DDiskSizeFormatter::K, DDiskSizeFormatter::B); + Q_ASSERT(i1 == 1000000); +} + +void TestDUtil::testDiskFormatterList() +{ + const DDiskSizeFormatter diskFormatter = DDiskSizeFormatter(); + + // 1351223412.1234 KB == 1 TB + 351 GB + 223 MB + 412 KB + 123.4 B + const auto r = diskFormatter.formatAsUnitList(1351223412.1234, DDiskSizeFormatter::K); + Q_ASSERT(r[0].first == 1 && r[0].second == DDiskSizeFormatter::T); + Q_ASSERT(r[1].first == 351 && r[1].second == DDiskSizeFormatter::G); + Q_ASSERT(r[2].first == 223 && r[2].second == DDiskSizeFormatter::M); + Q_ASSERT(r[3].first == 412 && r[3].second == DDiskSizeFormatter::K); + + // TODO: test failed +// Q_ASSERT(r[4].first == 123.4 && r[4].second == DiskSizeFormatter::B); +} + +void TestDUtil::testDiskFormatter1024() +{ + const DDiskSizeFormatter diskFormatter = DDiskSizeFormatter().rate(1024); + + // 1024 K == 1 M + const auto d0 = diskFormatter.format(1024, DDiskSizeFormatter::K); + Q_ASSERT(d0.first == 1 && d0.second == DDiskSizeFormatter::M); + + // 100000000000 B == 93.13225746154785 G + const auto d1 = diskFormatter.format(100000000000, DDiskSizeFormatter::B); + Q_ASSERT(qFuzzyCompare(93.13225746154785, d1.first) && d1.second == DDiskSizeFormatter::G); + + // 100000000000 B == 0.09094947017729282 T + const auto d2 = diskFormatter.formatAs(100000000000, DDiskSizeFormatter::B, DDiskSizeFormatter::T); + Q_ASSERT(qFuzzyCompare(0.09094947017729282, d2)); +} diff --git a/tests/dutiltester.h b/tests/dutiltester.h index 2fddddf..cab11cc 100644 --- a/tests/dutiltester.h +++ b/tests/dutiltester.h @@ -30,6 +30,11 @@ private Q_SLOTS: void testLogPath(); void testPathChange(); void testDSingleton(); + void testTimeFormatter(); + void testTimeFormatterList(); + void testDiskFormatter(); + void testDiskFormatterList(); + void testDiskFormatter1024(); }; #endif // DUTILTESTER_H