Skip to content

Commit 483c506

Browse files
authored
Merge pull request #204 from scratchcpp/days_since_2000_block
Implement days since 2000 block
2 parents 148f0da + 151a485 commit 483c506

File tree

10 files changed

+97
-13
lines changed

10 files changed

+97
-13
lines changed

src/blocks/sensingblocks.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
#include <scratchcpp/itimer.h>
77
#include "sensingblocks.h"
88

9+
#include "../engine/internal/clock.h"
10+
911
using namespace libscratchcpp;
1012

13+
IClock *SensingBlocks::clock = Clock::instance().get();
14+
1115
std::string SensingBlocks::name() const
1216
{
1317
return "Sensing";
@@ -18,6 +22,7 @@ void SensingBlocks::registerBlocks(IEngine *engine)
1822
// Blocks
1923
engine->addCompileFunction(this, "sensing_timer", &compileTimer);
2024
engine->addCompileFunction(this, "sensing_resettimer", &compileResetTimer);
25+
engine->addCompileFunction(this, "sensing_dayssince2000", &compileDaysSince2000);
2126
}
2227

2328
void SensingBlocks::compileTimer(Compiler *compiler)
@@ -30,6 +35,11 @@ void SensingBlocks::compileResetTimer(Compiler *compiler)
3035
compiler->addFunctionCall(&resetTimer);
3136
}
3237

38+
void SensingBlocks::compileDaysSince2000(Compiler *compiler)
39+
{
40+
compiler->addFunctionCall(&daysSince2000);
41+
}
42+
3343
unsigned int SensingBlocks::timer(VirtualMachine *vm)
3444
{
3545
vm->addReturnValue(vm->engine()->timer()->value());
@@ -41,3 +51,11 @@ unsigned int SensingBlocks::resetTimer(VirtualMachine *vm)
4151
vm->engine()->timer()->reset();
4252
return 0;
4353
}
54+
55+
unsigned int SensingBlocks::daysSince2000(VirtualMachine *vm)
56+
{
57+
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(clock->currentSystemTime().time_since_epoch()).count();
58+
vm->addReturnValue(ms / 86400000.0 - 10957);
59+
60+
return 0;
61+
}

src/blocks/sensingblocks.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#pragma once
44

55
#include <scratchcpp/iblocksection.h>
6+
#include "../engine/internal/clock.h"
67

78
namespace libscratchcpp
89
{
@@ -17,9 +18,13 @@ class SensingBlocks : public IBlockSection
1718

1819
static void compileTimer(Compiler *compiler);
1920
static void compileResetTimer(Compiler *compiler);
21+
static void compileDaysSince2000(Compiler *compiler);
2022

2123
static unsigned int timer(VirtualMachine *vm);
2224
static unsigned int resetTimer(VirtualMachine *vm);
25+
static unsigned int daysSince2000(VirtualMachine *vm);
26+
27+
static IClock *clock;
2328
};
2429

2530
} // namespace libscratchcpp

src/engine/internal/clock.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ std::shared_ptr<Clock> Clock::instance()
1515
return m_instance;
1616
}
1717

18-
std::chrono::steady_clock::time_point Clock::currentTime() const
18+
std::chrono::steady_clock::time_point Clock::currentSteadyTime() const
1919
{
2020
return std::chrono::steady_clock::now();
2121
}
22+
23+
std::chrono::system_clock::time_point Clock::currentSystemTime() const
24+
{
25+
return std::chrono::system_clock::now();
26+
}

src/engine/internal/clock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class Clock : public IClock
1616

1717
static std::shared_ptr<Clock> instance();
1818

19-
std::chrono::steady_clock::time_point currentTime() const override;
19+
std::chrono::steady_clock::time_point currentSteadyTime() const override;
20+
std::chrono::system_clock::time_point currentSystemTime() const override;
2021

2122
private:
2223
static std::shared_ptr<Clock> m_instance;

src/engine/internal/iclock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ class IClock
1212
public:
1313
virtual ~IClock() { }
1414

15-
virtual std::chrono::steady_clock::time_point currentTime() const = 0;
15+
virtual std::chrono::steady_clock::time_point currentSteadyTime() const = 0;
16+
virtual std::chrono::system_clock::time_point currentSystemTime() const = 0;
1617
};
1718

1819
} // namespace libscratchcpp

src/engine/internal/timer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Timer::Timer(IClock *clock) :
2222

2323
double Timer::value() const
2424
{
25-
return std::chrono::duration_cast<std::chrono::milliseconds>(m_clock->currentTime() - m_startTime).count() / 1000.0;
25+
return std::chrono::duration_cast<std::chrono::milliseconds>(m_clock->currentSteadyTime() - m_startTime).count() / 1000.0;
2626
}
2727

2828
void Timer::reset()
@@ -33,5 +33,5 @@ void Timer::reset()
3333
// Required to avoid calling the virtual method from the constructors
3434
void Timer::resetTimer()
3535
{
36-
m_startTime = m_clock->currentTime();
36+
m_startTime = m_clock->currentSteadyTime();
3737
}

test/blocks/sensing_blocks_test.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <scratchcpp/block.h>
33
#include <enginemock.h>
44
#include <timermock.h>
5+
#include <clockmock.h>
56

67
#include "../common.h"
78
#include "blocks/sensingblocks.h"
@@ -24,6 +25,7 @@ class SensingBlocksTest : public testing::Test
2425
EngineMock m_engineMock;
2526
Engine m_engine;
2627
TimerMock m_timerMock;
28+
ClockMock m_clockMock;
2729
};
2830

2931
TEST_F(SensingBlocksTest, Name)
@@ -41,6 +43,7 @@ TEST_F(SensingBlocksTest, RegisterBlocks)
4143
// Blocks
4244
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_timer", &SensingBlocks::compileTimer)).Times(1);
4345
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_resettimer", &SensingBlocks::compileResetTimer)).Times(1);
46+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_dayssince2000", &SensingBlocks::compileDaysSince2000)).Times(1);
4447

4548
m_section->registerBlocks(&m_engineMock);
4649
}
@@ -111,3 +114,39 @@ TEST_F(SensingBlocksTest, ResetTimerImpl)
111114

112115
ASSERT_EQ(vm.registerCount(), 0);
113116
}
117+
118+
TEST_F(SensingBlocksTest, DaysSince2000)
119+
{
120+
Compiler compiler(&m_engineMock);
121+
122+
auto block = std::make_shared<Block>("a", "sensing_dayssince2000");
123+
124+
EXPECT_CALL(m_engineMock, functionIndex(&SensingBlocks::daysSince2000)).WillOnce(Return(0));
125+
126+
compiler.init();
127+
compiler.setBlock(block);
128+
SensingBlocks::compileDaysSince2000(&compiler);
129+
compiler.end();
130+
131+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT }));
132+
}
133+
134+
TEST_F(SensingBlocksTest, DaysSince2000Impl)
135+
{
136+
static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };
137+
static BlockFunc functions[] = { &SensingBlocks::daysSince2000 };
138+
139+
VirtualMachine vm(nullptr, &m_engineMock, nullptr);
140+
vm.setFunctions(functions);
141+
142+
std::chrono::system_clock::time_point time(std::chrono::milliseconds(1011243120562)); // Jan 17 2002 04:52:00
143+
EXPECT_CALL(m_clockMock, currentSystemTime()).WillOnce(Return(time));
144+
145+
SensingBlocks::clock = &m_clockMock;
146+
vm.setBytecode(bytecode);
147+
vm.run();
148+
SensingBlocks::clock = Clock::instance().get();
149+
150+
ASSERT_EQ(vm.registerCount(), 1);
151+
ASSERT_EQ(vm.getInput(0, 1)->toDouble(), 747.20278428240817);
152+
}

test/clock/clock_test.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,29 @@
55

66
using namespace libscratchcpp;
77

8-
TEST(ClockTest, CurrentTime)
8+
TEST(ClockTest, CurrentSteadyTime)
99
{
1010
auto clock = Clock::instance();
1111
ASSERT_TRUE(clock);
1212

1313
auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
1414
double currentTimeMs = std::round(currentTime.time_since_epoch().count() / 10) * 10;
1515

16-
auto reportedTime = std::chrono::time_point_cast<std::chrono::milliseconds>(clock->currentTime());
16+
auto reportedTime = std::chrono::time_point_cast<std::chrono::milliseconds>(clock->currentSteadyTime());
17+
double reportedTimeMs = std::round(reportedTime.time_since_epoch().count() / 10) * 10;
18+
19+
ASSERT_EQ(reportedTimeMs, currentTimeMs);
20+
}
21+
22+
TEST(ClockTest, CurrentSystemTime)
23+
{
24+
auto clock = Clock::instance();
25+
ASSERT_TRUE(clock);
26+
27+
auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
28+
double currentTimeMs = std::round(currentTime.time_since_epoch().count() / 10) * 10;
29+
30+
auto reportedTime = std::chrono::time_point_cast<std::chrono::milliseconds>(clock->currentSystemTime());
1731
double reportedTimeMs = std::round(reportedTime.time_since_epoch().count() / 10) * 10;
1832

1933
ASSERT_EQ(reportedTimeMs, currentTimeMs);

test/mocks/clockmock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ using namespace libscratchcpp;
88
class ClockMock : public IClock
99
{
1010
public:
11-
MOCK_METHOD(std::chrono::steady_clock::time_point, currentTime, (), (const override));
11+
MOCK_METHOD(std::chrono::steady_clock::time_point, currentSteadyTime, (), (const, override));
12+
MOCK_METHOD(std::chrono::system_clock::time_point, currentSystemTime, (), (const, override));
1213
};

test/timer/timer_test.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ TEST(TimerTest, ValueAndReset)
1212
ClockMock clock;
1313

1414
std::chrono::steady_clock::time_point startTime(std::chrono::milliseconds(50));
15-
EXPECT_CALL(clock, currentTime()).WillOnce(Return(startTime));
15+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(startTime));
1616
Timer timer(&clock);
1717

1818
std::chrono::steady_clock::time_point time1(std::chrono::milliseconds(73));
19-
EXPECT_CALL(clock, currentTime()).WillOnce(Return(time1));
19+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(time1));
2020
ASSERT_EQ(timer.value(), 0.023);
2121

2222
std::chrono::steady_clock::time_point time2(std::chrono::milliseconds(15432));
23-
EXPECT_CALL(clock, currentTime()).WillOnce(Return(time2));
23+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(time2));
2424
ASSERT_EQ(timer.value(), 15.382);
2525

2626
std::chrono::steady_clock::time_point time3(std::chrono::milliseconds(16025));
27-
EXPECT_CALL(clock, currentTime()).WillOnce(Return(time3));
27+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(time3));
2828
timer.reset();
2929

3030
std::chrono::steady_clock::time_point time4(std::chrono::milliseconds(24632));
31-
EXPECT_CALL(clock, currentTime()).WillOnce(Return(time4));
31+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(time4));
3232
ASSERT_EQ(timer.value(), 8.607);
3333
}

0 commit comments

Comments
 (0)