Skip to content

Commit 05b0fbd

Browse files
committed
Implement sensing_current block
1 parent 86f1ce0 commit 05b0fbd

File tree

3 files changed

+249
-0
lines changed

3 files changed

+249
-0
lines changed

src/blocks/sensingblocks.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ void SensingBlocks::registerBlocks(IEngine *engine)
5959
engine->addCompileFunction(this, "sensing_timer", &compileTimer);
6060
engine->addCompileFunction(this, "sensing_resettimer", &compileResetTimer);
6161
engine->addCompileFunction(this, "sensing_of", &compileOf);
62+
engine->addCompileFunction(this, "sensing_current", &compileCurrent);
6263
}
6364

6465
void SensingBlocks::onInit(IEngine *engine)
@@ -342,6 +343,30 @@ CompilerValue *SensingBlocks::compileOf(Compiler *compiler)
342343
return compiler->addConstValue(0.0);
343344
}
344345

346+
CompilerValue *SensingBlocks::compileCurrent(Compiler *compiler)
347+
{
348+
Field *field = compiler->field("CURRENTMENU");
349+
assert(field);
350+
std::string option = field->value().toString();
351+
352+
if (option == "YEAR")
353+
return compiler->addFunctionCall("sensing_current_year", Compiler::StaticType::Number);
354+
else if (option == "MONTH")
355+
return compiler->addFunctionCall("sensing_current_month", Compiler::StaticType::Number);
356+
else if (option == "DATE")
357+
return compiler->addFunctionCall("sensing_current_date", Compiler::StaticType::Number);
358+
else if (option == "DAYOFWEEK")
359+
return compiler->addFunctionCall("sensing_current_day_of_week", Compiler::StaticType::Number);
360+
else if (option == "HOUR")
361+
return compiler->addFunctionCall("sensing_current_hour", Compiler::StaticType::Number);
362+
else if (option == "MINUTE")
363+
return compiler->addFunctionCall("sensing_current_minute", Compiler::StaticType::Number);
364+
else if (option == "SECOND")
365+
return compiler->addFunctionCall("sensing_current_second", Compiler::StaticType::Number);
366+
else
367+
return compiler->addConstValue(Value());
368+
}
369+
345370
void SensingBlocks::onAnswer(const std::string &answer)
346371
{
347372
// https://github.com/scratchfoundation/scratch-vm/blob/6055823f203a696165084b873e661713806583ec/src/blocks/scratch3_sensing.js#L99-L115
@@ -701,3 +726,52 @@ extern "C" ValueData sensing_variable_of_target(Target *target, const StringPtr
701726
value_init(&ret);
702727
return ret;
703728
}
729+
730+
extern "C" double sensing_current_year()
731+
{
732+
time_t now = time(0);
733+
tm *ltm = localtime(&now);
734+
return ltm->tm_year + 1900;
735+
}
736+
737+
extern "C" double sensing_current_month()
738+
{
739+
time_t now = time(0);
740+
tm *ltm = localtime(&now);
741+
return ltm->tm_mon + 1;
742+
}
743+
744+
extern "C" double sensing_current_date()
745+
{
746+
time_t now = time(0);
747+
tm *ltm = localtime(&now);
748+
return ltm->tm_mday;
749+
}
750+
751+
extern "C" double sensing_current_day_of_week()
752+
{
753+
time_t now = time(0);
754+
tm *ltm = localtime(&now);
755+
return ltm->tm_wday + 1;
756+
}
757+
758+
extern "C" double sensing_current_hour()
759+
{
760+
time_t now = time(0);
761+
tm *ltm = localtime(&now);
762+
return ltm->tm_hour;
763+
}
764+
765+
extern "C" double sensing_current_minute()
766+
{
767+
time_t now = time(0);
768+
tm *ltm = localtime(&now);
769+
return ltm->tm_min;
770+
}
771+
772+
extern "C" double sensing_current_second()
773+
{
774+
time_t now = time(0);
775+
tm *ltm = localtime(&now);
776+
return ltm->tm_sec;
777+
}

src/blocks/sensingblocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class SensingBlocks : public IExtension
6161
static CompilerValue *compileTimer(Compiler *compiler);
6262
static CompilerValue *compileResetTimer(Compiler *compiler);
6363
static CompilerValue *compileOf(Compiler *compiler);
64+
static CompilerValue *compileCurrent(Compiler *compiler);
6465

6566
static void onAnswer(const std::string &answer);
6667
static void enqueueAsk(const std::string &question, Thread *thread);

test/blocks/sensing_blocks_test.cpp

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,3 +2571,177 @@ TEST_F(SensingBlocksTest, Of_PreferPropertiesOverVariables_Runtime)
25712571
ASSERT_EQ(value_toDouble(&value), -78.25);
25722572
value_free(&value);
25732573
}
2574+
2575+
TEST_F(SensingBlocksTest, Current_Year)
2576+
{
2577+
auto targetMock = std::make_shared<TargetMock>();
2578+
2579+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2580+
builder.addBlock("sensing_current");
2581+
builder.addDropdownField("CURRENTMENU", "YEAR");
2582+
Block *block = builder.currentBlock();
2583+
2584+
Compiler compiler(&m_engineMock, targetMock.get());
2585+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2586+
Script script(targetMock.get(), block, &m_engineMock);
2587+
script.setCode(code);
2588+
Thread thread(targetMock.get(), &m_engineMock, &script);
2589+
2590+
ValueData value = thread.runReporter();
2591+
time_t now = time(0);
2592+
tm *ltm = localtime(&now);
2593+
ASSERT_EQ(value_toDouble(&value), ltm->tm_year + 1900);
2594+
value_free(&value);
2595+
}
2596+
2597+
TEST_F(SensingBlocksTest, Current_Month)
2598+
{
2599+
auto targetMock = std::make_shared<TargetMock>();
2600+
2601+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2602+
builder.addBlock("sensing_current");
2603+
builder.addDropdownField("CURRENTMENU", "MONTH");
2604+
Block *block = builder.currentBlock();
2605+
2606+
Compiler compiler(&m_engineMock, targetMock.get());
2607+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2608+
Script script(targetMock.get(), block, &m_engineMock);
2609+
script.setCode(code);
2610+
Thread thread(targetMock.get(), &m_engineMock, &script);
2611+
2612+
ValueData value = thread.runReporter();
2613+
time_t now = time(0);
2614+
tm *ltm = localtime(&now);
2615+
ASSERT_EQ(value_toDouble(&value), ltm->tm_mon + 1);
2616+
value_free(&value);
2617+
}
2618+
2619+
TEST_F(SensingBlocksTest, Current_Date)
2620+
{
2621+
auto targetMock = std::make_shared<TargetMock>();
2622+
2623+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2624+
builder.addBlock("sensing_current");
2625+
builder.addDropdownField("CURRENTMENU", "DATE");
2626+
Block *block = builder.currentBlock();
2627+
2628+
Compiler compiler(&m_engineMock, targetMock.get());
2629+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2630+
Script script(targetMock.get(), block, &m_engineMock);
2631+
script.setCode(code);
2632+
Thread thread(targetMock.get(), &m_engineMock, &script);
2633+
2634+
ValueData value = thread.runReporter();
2635+
time_t now = time(0);
2636+
tm *ltm = localtime(&now);
2637+
ASSERT_EQ(value_toDouble(&value), ltm->tm_mday);
2638+
value_free(&value);
2639+
}
2640+
2641+
TEST_F(SensingBlocksTest, Current_DayOfWeek)
2642+
{
2643+
auto targetMock = std::make_shared<TargetMock>();
2644+
2645+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2646+
builder.addBlock("sensing_current");
2647+
builder.addDropdownField("CURRENTMENU", "DAYOFWEEK");
2648+
Block *block = builder.currentBlock();
2649+
2650+
Compiler compiler(&m_engineMock, targetMock.get());
2651+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2652+
Script script(targetMock.get(), block, &m_engineMock);
2653+
script.setCode(code);
2654+
Thread thread(targetMock.get(), &m_engineMock, &script);
2655+
2656+
ValueData value = thread.runReporter();
2657+
time_t now = time(0);
2658+
tm *ltm = localtime(&now);
2659+
ASSERT_EQ(value_toDouble(&value), ltm->tm_wday + 1);
2660+
value_free(&value);
2661+
}
2662+
2663+
TEST_F(SensingBlocksTest, Current_Hour)
2664+
{
2665+
auto targetMock = std::make_shared<TargetMock>();
2666+
2667+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2668+
builder.addBlock("sensing_current");
2669+
builder.addDropdownField("CURRENTMENU", "HOUR");
2670+
Block *block = builder.currentBlock();
2671+
2672+
Compiler compiler(&m_engineMock, targetMock.get());
2673+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2674+
Script script(targetMock.get(), block, &m_engineMock);
2675+
script.setCode(code);
2676+
Thread thread(targetMock.get(), &m_engineMock, &script);
2677+
2678+
ValueData value = thread.runReporter();
2679+
time_t now = time(0);
2680+
tm *ltm = localtime(&now);
2681+
ASSERT_EQ(value_toDouble(&value), ltm->tm_hour);
2682+
value_free(&value);
2683+
}
2684+
2685+
TEST_F(SensingBlocksTest, Current_Minute)
2686+
{
2687+
auto targetMock = std::make_shared<TargetMock>();
2688+
2689+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2690+
builder.addBlock("sensing_current");
2691+
builder.addDropdownField("CURRENTMENU", "MINUTE");
2692+
Block *block = builder.currentBlock();
2693+
2694+
Compiler compiler(&m_engineMock, targetMock.get());
2695+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2696+
Script script(targetMock.get(), block, &m_engineMock);
2697+
script.setCode(code);
2698+
Thread thread(targetMock.get(), &m_engineMock, &script);
2699+
2700+
ValueData value = thread.runReporter();
2701+
time_t now = time(0);
2702+
tm *ltm = localtime(&now);
2703+
ASSERT_EQ(value_toDouble(&value), ltm->tm_min);
2704+
value_free(&value);
2705+
}
2706+
2707+
TEST_F(SensingBlocksTest, Current_Second)
2708+
{
2709+
auto targetMock = std::make_shared<TargetMock>();
2710+
2711+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2712+
builder.addBlock("sensing_current");
2713+
builder.addDropdownField("CURRENTMENU", "SECOND");
2714+
Block *block = builder.currentBlock();
2715+
2716+
Compiler compiler(&m_engineMock, targetMock.get());
2717+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2718+
Script script(targetMock.get(), block, &m_engineMock);
2719+
script.setCode(code);
2720+
Thread thread(targetMock.get(), &m_engineMock, &script);
2721+
2722+
ValueData value = thread.runReporter();
2723+
time_t now = time(0);
2724+
tm *ltm = localtime(&now);
2725+
ASSERT_EQ(value_toDouble(&value), ltm->tm_sec);
2726+
value_free(&value);
2727+
}
2728+
2729+
TEST_F(SensingBlocksTest, Current_Invalid)
2730+
{
2731+
auto targetMock = std::make_shared<TargetMock>();
2732+
2733+
ScriptBuilder builder(m_extension.get(), m_engine, targetMock);
2734+
builder.addBlock("sensing_current");
2735+
builder.addDropdownField("CURRENTMENU", "TEST");
2736+
Block *block = builder.currentBlock();
2737+
2738+
Compiler compiler(&m_engineMock, targetMock.get());
2739+
auto code = compiler.compile(block, Compiler::CodeType::Reporter);
2740+
Script script(targetMock.get(), block, &m_engineMock);
2741+
script.setCode(code);
2742+
Thread thread(targetMock.get(), &m_engineMock, &script);
2743+
2744+
ValueData value = thread.runReporter();
2745+
ASSERT_EQ(value_toDouble(&value), 0.0);
2746+
value_free(&value);
2747+
}

0 commit comments

Comments
 (0)