Compare commits
60 Commits
Author | SHA1 | Date | |
---|---|---|---|
f1880897d4 | |||
ad2e82060d | |||
d1bb19e30e | |||
280963d1eb | |||
9fadf49b0e | |||
3c2be25384 | |||
e1f623a94d | |||
cb5f9648f5 | |||
9158cfe4f6 | |||
0b763978f2 | |||
25fded6afb | |||
fc6fb0811f | |||
49bedcbcc5 | |||
32876f4584 | |||
da9bea30b5 | |||
d0aa68aeee | |||
51731fbbc9 | |||
751ea1494b | |||
dfe84471e8 | |||
0f3de6cf07 | |||
21195e4abf | |||
c992100a38 | |||
20a4673f98 | |||
966fd81870 | |||
cb9d2aeb39 | |||
3cee55f4c2 | |||
3815d2fd3b | |||
1453b7e0a3 | |||
6fb5c54280 | |||
9d5ca35e83 | |||
893dd0f9c4 | |||
c3419c0b74 | |||
a4164470d8 | |||
0dd5ab9bde | |||
e93e659e8a | |||
8357372fb5 | |||
54cb076002 | |||
dbd3eb464b | |||
10cd39a4ec | |||
fddc4e647a | |||
798a351f15 | |||
e61dffff03 | |||
b9f5096480 | |||
9912d68c8b | |||
951b9be6e4 | |||
aa8635c4e7 | |||
4e4f5495da | |||
f64bf57000 | |||
f1242724b5 | |||
cd0c9df86e | |||
337d42287a | |||
ce3383f1b7 | |||
e51721303a | |||
50f6c77fdb | |||
5ed0135124 | |||
892a2d585f | |||
9890f2340a | |||
109b809909 | |||
16b9a5027d | |||
cbe68b3199 |
@ -14,7 +14,7 @@ function accelerate() {
|
|||||||
}
|
}
|
||||||
function update() {
|
function update() {
|
||||||
brick.clearScreen()
|
brick.clearScreen()
|
||||||
brick.printLine("speed: " + speed, 1)
|
brick.showString("speed: " + speed, 1)
|
||||||
motors.largeBC.setSpeed(speed)
|
motors.largeBC.setSpeed(speed)
|
||||||
}
|
}
|
||||||
sensors.touch2.onEvent(TouchSensorEvent.Pressed, function () {
|
sensors.touch2.onEvent(TouchSensorEvent.Pressed, function () {
|
||||||
|
@ -7,5 +7,5 @@ loops.forever(function () {
|
|||||||
})
|
})
|
||||||
motors.largeBC.setSpeed(-20);
|
motors.largeBC.setSpeed(-20);
|
||||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
||||||
motors.stopAllMotors();
|
motors.largeBC.stop();
|
||||||
```
|
```
|
||||||
|
@ -9,5 +9,5 @@ loops.forever(function () {
|
|||||||
})
|
})
|
||||||
motors.largeBC.setSpeed(-20);
|
motors.largeBC.setSpeed(-20);
|
||||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
||||||
motors.stopAllMotors();
|
motors.largeBC.stop();
|
||||||
```
|
```
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
let beep = false
|
let beep = false
|
||||||
beep = true
|
beep = true
|
||||||
control.runInBackground(function () {
|
control.runInBackground(function () {
|
||||||
motors.largeB.setSpeed(-20)
|
motors.largeBC.setSpeed(-20)
|
||||||
motors.largeC.setSpeed(-20)
|
|
||||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear)
|
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear)
|
||||||
motors.stopAllMotors()
|
motors.largeBC.stop()
|
||||||
beep = false
|
beep = false
|
||||||
})
|
})
|
||||||
control.runInBackground(function () {
|
control.runInBackground(function () {
|
||||||
|
215
docs/examples/core-set/gyroboy-labview.md
Normal file
215
docs/examples/core-set/gyroboy-labview.md
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
# Gyroboy LabView
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
let mSum = 0;
|
||||||
|
let mPos = 0;
|
||||||
|
let mSpd = 0;
|
||||||
|
let mD = 0;
|
||||||
|
let mDP1 = 0;
|
||||||
|
let mDP2 = 0;
|
||||||
|
let mDP3 = 0;
|
||||||
|
let Crdv = 0;
|
||||||
|
let cLo = 0;
|
||||||
|
let gAng = 0;
|
||||||
|
let ok = false;
|
||||||
|
let pwr = 0;
|
||||||
|
let Cstr = 0;
|
||||||
|
let Cdrv = 0;
|
||||||
|
let gMn = 0;
|
||||||
|
let gMx = 0;
|
||||||
|
let gSum = 0;
|
||||||
|
let gyro = 0;
|
||||||
|
let gOS = 0;
|
||||||
|
let gSpd = 0;
|
||||||
|
let tInt = 0.014;
|
||||||
|
let lpwr = 0
|
||||||
|
let rpwr = 0
|
||||||
|
let tStart = 0
|
||||||
|
let st = 0
|
||||||
|
let oldDr = 0
|
||||||
|
|
||||||
|
function RST() {
|
||||||
|
motors.largeA.reset()
|
||||||
|
motors.largeD.reset()
|
||||||
|
motors.largeA.setRegulated(false)
|
||||||
|
motors.largeD.setRegulated(false)
|
||||||
|
sensors.gyro2.reset()
|
||||||
|
sensors.gyro2.rate()
|
||||||
|
control.timer2.reset()
|
||||||
|
loops.pause(5000)
|
||||||
|
mSum = 0;
|
||||||
|
mPos = 0;
|
||||||
|
mD = 0;
|
||||||
|
mDP1 = 0;
|
||||||
|
mDP2 = 0;
|
||||||
|
mDP3 = 0;
|
||||||
|
Crdv = 0;
|
||||||
|
cLo = 0;
|
||||||
|
gAng = 0;
|
||||||
|
ok = false;
|
||||||
|
pwr = 0;
|
||||||
|
st = 0;
|
||||||
|
Cstr = 0;
|
||||||
|
Cdrv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function OS() {
|
||||||
|
// OSL
|
||||||
|
do {
|
||||||
|
gMn = 1000;
|
||||||
|
gMx = -100;
|
||||||
|
gSum = 0;
|
||||||
|
// gChk
|
||||||
|
for (let i = 0; i < 200; i++) {
|
||||||
|
gyro = sensors.gyro2.rate()
|
||||||
|
gSum = gyro;
|
||||||
|
gMx = Math.max(gMx, gyro)
|
||||||
|
gMn = Math.min(gMn, gyro)
|
||||||
|
loops.pause(4);
|
||||||
|
}
|
||||||
|
} while (gMx - gMn > 2);
|
||||||
|
gOS = gSum / 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GT() {
|
||||||
|
if (cLo == 0) {
|
||||||
|
tInt = 0.014;
|
||||||
|
control.timer1.reset();
|
||||||
|
} else {
|
||||||
|
tInt = control.timer1.seconds() / cLo;
|
||||||
|
}
|
||||||
|
cLo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GG() {
|
||||||
|
gyro = sensors.gyro2.rate();
|
||||||
|
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
|
||||||
|
gSpd = gyro - gOS;
|
||||||
|
gAng = gAng + tInt * gSpd;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GM() {
|
||||||
|
let temp = mSum
|
||||||
|
mSum = motors.largeD.angle() + motors.largeA.angle();
|
||||||
|
mD = mSum - temp;
|
||||||
|
mPos = mPos + mD;
|
||||||
|
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
|
||||||
|
mDP3 = mDP2;
|
||||||
|
mDP2 = mDP1;
|
||||||
|
mDP1 = mD;
|
||||||
|
}
|
||||||
|
|
||||||
|
function EQ() {
|
||||||
|
mPos = mPos - Cdrv * tInt;
|
||||||
|
pwr = (0.8 * gSpd + 15 * gAng) + (0.08 * mSpd + 0.12 * mPos) - 0.01 * Cdrv
|
||||||
|
if (pwr > 100) pwr = 100
|
||||||
|
else if (pwr < -100) pwr = -100
|
||||||
|
}
|
||||||
|
|
||||||
|
function cntrl() {
|
||||||
|
mPos = mPos - tInt * Cdrv
|
||||||
|
lpwr = (pwr + Cstr * 0.1)
|
||||||
|
rpwr = (pwr - Cstr * 0.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CHK() {
|
||||||
|
if (Math.abs(pwr) < 100)
|
||||||
|
control.timer2.reset();
|
||||||
|
if (control.timer2.seconds() > 2) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// M
|
||||||
|
loops.forever(function () {
|
||||||
|
RST();
|
||||||
|
brick.showImage(images.eyesSleeping)
|
||||||
|
OS()
|
||||||
|
gAng = -0.25;
|
||||||
|
music.playSoundEffect(sounds.movementsSpeedUp)
|
||||||
|
brick.showImage(images.eyesAwake)
|
||||||
|
st = 1;
|
||||||
|
// BALANCE
|
||||||
|
while (!ok) {
|
||||||
|
GT();
|
||||||
|
let t1 = control.timer1.millis()
|
||||||
|
GG();
|
||||||
|
GM();
|
||||||
|
EQ();
|
||||||
|
cntrl();
|
||||||
|
motors.largeA.setSpeed(lpwr)
|
||||||
|
motors.largeD.setSpeed(rpwr)
|
||||||
|
CHK()
|
||||||
|
let t2 = control.timer1.millis();
|
||||||
|
let p = 5 - (t2 - t1);
|
||||||
|
loops.pause(Math.max(1, p))
|
||||||
|
}
|
||||||
|
motors.stopAllMotors()
|
||||||
|
st = 0;
|
||||||
|
brick.setLight(BrickLight.RedPulse);
|
||||||
|
brick.showImage(images.eyesKnockedOut)
|
||||||
|
music.playSoundEffect(sounds.movementsSpeedDown)
|
||||||
|
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
|
||||||
|
brick.setLight(BrickLight.Off);
|
||||||
|
})
|
||||||
|
|
||||||
|
// BHV
|
||||||
|
loops.forever(function () {
|
||||||
|
switch (st) {
|
||||||
|
case 0:
|
||||||
|
Cdrv = 0;
|
||||||
|
Cstr = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Cdrv = 40;
|
||||||
|
loops.pause(4000);
|
||||||
|
Cdrv = 0;
|
||||||
|
music.playTone(1000, 100);
|
||||||
|
st = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (sensors.color1.color()) {
|
||||||
|
case ColorSensorColor.Red:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cdrv = 0;
|
||||||
|
Cstr = 0;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.Green:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cdrv = 150;
|
||||||
|
Cstr = 0;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.Blue:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cstr = 70;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.Yellow:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cstr = -70;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.White:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cdrv = -75;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sensors.ultrasonic4.distance() < 25) {
|
||||||
|
Cstr = 0;
|
||||||
|
oldDr = Cdrv;
|
||||||
|
Cdrv = -10;
|
||||||
|
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
|
||||||
|
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
|
||||||
|
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
|
||||||
|
if (Math.randomRange(-1, 1) >= 1)
|
||||||
|
Cstr = 70;
|
||||||
|
else
|
||||||
|
Cstr = -70;
|
||||||
|
loops.pause(4000);
|
||||||
|
music.playTone(2000, 100)
|
||||||
|
Cstr = 0;
|
||||||
|
Cdrv = oldDr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
loops.pause(80);
|
||||||
|
})
|
||||||
|
```
|
390
docs/examples/core-set/puppy-labview.md
Normal file
390
docs/examples/core-set/puppy-labview.md
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
# Puppy
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
let P_T = 0;
|
||||||
|
let ISS = 0;
|
||||||
|
let F_T = 0;
|
||||||
|
let P_C = 0;
|
||||||
|
let F_C = 0;
|
||||||
|
let DB_S = 0;
|
||||||
|
let NS = false;
|
||||||
|
let IBP = 0;
|
||||||
|
let IAP = 0;
|
||||||
|
let C = false;
|
||||||
|
let TC = false;
|
||||||
|
let OTC = false;
|
||||||
|
let COL = 0;
|
||||||
|
let OCOL = 0;
|
||||||
|
let _C = false;
|
||||||
|
let GTO = 0;
|
||||||
|
|
||||||
|
function DN() {
|
||||||
|
motors.largeAD.setBrake(true);
|
||||||
|
motors.largeAD.tank(50, 50, 1, MoveUnit.Seconds);
|
||||||
|
loops.pause(100);
|
||||||
|
motors.largeA.clearCounts()
|
||||||
|
motors.largeD.clearCounts()
|
||||||
|
}
|
||||||
|
|
||||||
|
function MNRH() {
|
||||||
|
motors.mediumC.setBrake(true)
|
||||||
|
brick.showImage(images.legoEv3icon)
|
||||||
|
brick.setLight(BrickLight.OrangePulse)
|
||||||
|
while (!brick.buttonEnter.wasPressed()) {
|
||||||
|
if (brick.buttonUp.wasPressed()) {
|
||||||
|
motors.mediumC.setSpeed(-100);
|
||||||
|
} else if (brick.buttonDown.wasPressed()) {
|
||||||
|
motors.mediumC.setSpeed(100);
|
||||||
|
} else {
|
||||||
|
motors.mediumC.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
motors.mediumC.stop();
|
||||||
|
motors.mediumC.clearCounts();
|
||||||
|
brick.setLight(BrickLight.Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IS(t: number) {
|
||||||
|
ISS = t;
|
||||||
|
switch (t) {
|
||||||
|
case 0:
|
||||||
|
brick.showImage(images.eyesNeutral);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
brick.showImage(images.eyesSleeping);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
brick.showImage(images.eyesTear);
|
||||||
|
// draw rect...
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
brick.showImage(images.eyesHurt);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
brick.showImage(images.eyesAngry);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
brick.showImage(images.eyesTiredMiddle);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
brick.showImage(images.eyesTiredRight);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
brick.showImage(images.eyesTiredLeft);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
brick.showImage(images.eyesLove);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function UP() {
|
||||||
|
if (motors.largeA.angle() > -50) {
|
||||||
|
control.runInBackground(function () {
|
||||||
|
motors.largeD.clearCounts()
|
||||||
|
motors.largeD.setSpeed(-35);
|
||||||
|
pauseUntil(() => motors.largeD.angle() < -25);
|
||||||
|
motors.largeD.stop();
|
||||||
|
motors.largeD.setRegulated(false)
|
||||||
|
motors.largeD.setSpeed(-15)
|
||||||
|
pauseUntil(() => motors.largeD.angle() < -65);
|
||||||
|
motors.largeD.stop();
|
||||||
|
})
|
||||||
|
motors.largeA.clearCounts()
|
||||||
|
motors.largeA.setSpeed(-35);
|
||||||
|
pauseUntil(() => motors.largeA.angle() < -25);
|
||||||
|
motors.largeA.stop();
|
||||||
|
motors.largeA.setRegulated(false)
|
||||||
|
motors.largeA.setSpeed(-15)
|
||||||
|
pauseUntil(() => motors.largeA.angle() < -65);
|
||||||
|
motors.largeA.stop();
|
||||||
|
|
||||||
|
loops.pause(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function RST() {
|
||||||
|
P_T = Math.randomRange(3, 6);
|
||||||
|
F_T = Math.randomRange(2, 4);
|
||||||
|
P_C = 1;
|
||||||
|
F_C = 1;
|
||||||
|
control.timer1.reset();
|
||||||
|
control.timer2.reset();
|
||||||
|
control.timer3.reset();
|
||||||
|
CS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function CS(db: number) {
|
||||||
|
if (DB_S != db) {
|
||||||
|
DB_S = db;
|
||||||
|
NS = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function MON() {
|
||||||
|
if (control.timer2.seconds() > 10) {
|
||||||
|
control.timer2.reset();
|
||||||
|
P_C--;
|
||||||
|
if (P_C < 0) {
|
||||||
|
P_C = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (control.timer1.seconds() > 20) {
|
||||||
|
control.timer1.reset()
|
||||||
|
F_C--;
|
||||||
|
if (F_C < 0) {
|
||||||
|
F_C = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (control.timer3.seconds() > 30) {
|
||||||
|
control.timer3.reset();
|
||||||
|
CS(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function UIS() {
|
||||||
|
if (control.timer5.seconds() > IBP) {
|
||||||
|
control.timer5.reset();
|
||||||
|
if (ISS == 1) {
|
||||||
|
ISS = 6;
|
||||||
|
IBP = Math.randomRange(1, 5);
|
||||||
|
} else {
|
||||||
|
ISS = 1;
|
||||||
|
IBP = 0.25;
|
||||||
|
}
|
||||||
|
IS(ISS);
|
||||||
|
}
|
||||||
|
if (control.timer6.seconds() > IAP) {
|
||||||
|
if (ISS != 1) {
|
||||||
|
control.timer6.reset();
|
||||||
|
IAP = Math.randomRange(1, 10)
|
||||||
|
if (ISS != 7) {
|
||||||
|
ISS = 7
|
||||||
|
} else {
|
||||||
|
ISS = 6;
|
||||||
|
}
|
||||||
|
IS(ISS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function UPDB() {
|
||||||
|
if ((P_T == P_C) && (F_T == F_C)) {
|
||||||
|
CS(6);
|
||||||
|
}
|
||||||
|
if ((P_T > P_C) && (F_T < F_C)) {
|
||||||
|
CS(3);
|
||||||
|
}
|
||||||
|
if ((P_T < P_C) && (F_T > F_C)) {
|
||||||
|
CS(5);
|
||||||
|
}
|
||||||
|
if ((P_C == 0) && (F_C > 0)) {
|
||||||
|
CS(2)
|
||||||
|
}
|
||||||
|
if (F_C == 0) {
|
||||||
|
CS(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function PTC() {
|
||||||
|
C = false;
|
||||||
|
OTC = TC;
|
||||||
|
TC = sensors.touch1.isPressed()
|
||||||
|
if (TC != OTC && TC) {
|
||||||
|
P_C++;
|
||||||
|
control.timer3.reset();
|
||||||
|
if (DB_S != 4) {
|
||||||
|
IS(2);
|
||||||
|
music.playSoundEffect(sounds.animalsDogSniff);
|
||||||
|
C = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FDC() {
|
||||||
|
OCOL = COL;
|
||||||
|
COL = sensors.color4.color();
|
||||||
|
_C = false;
|
||||||
|
if ((COL != 0) && (OCOL != COL)) {
|
||||||
|
F_C++;
|
||||||
|
_C = true;
|
||||||
|
control.timer3.reset();
|
||||||
|
IS(2);
|
||||||
|
music.playSoundEffect(sounds.expressionsCrunching)
|
||||||
|
}
|
||||||
|
return _C;
|
||||||
|
}
|
||||||
|
|
||||||
|
function IDL() {
|
||||||
|
if (NS) {
|
||||||
|
NS = false;
|
||||||
|
UP();
|
||||||
|
}
|
||||||
|
UIS();
|
||||||
|
UPDB();
|
||||||
|
PTC();
|
||||||
|
FDC();
|
||||||
|
}
|
||||||
|
|
||||||
|
function MHT(Pos: number) {
|
||||||
|
let _R = Pos - motors.mediumC.angle();
|
||||||
|
if (_R >= 0) {
|
||||||
|
motors.mediumC.setSpeed(100, _R, MoveUnit.Degrees);
|
||||||
|
} else {
|
||||||
|
motors.mediumC.setSpeed(-100, Math.abs(_R), MoveUnit.Degrees);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function SLP() {
|
||||||
|
if (NS) {
|
||||||
|
NS = false;
|
||||||
|
IS(5)
|
||||||
|
DN()
|
||||||
|
MHT(3000)
|
||||||
|
IS(1)
|
||||||
|
music.playSoundEffect(sounds.expressionsSnoring)
|
||||||
|
}
|
||||||
|
if (sensors.touch1.isPressed() || brick.buttonEnter.isPressed()) {
|
||||||
|
music.stopAllSounds();
|
||||||
|
control.timer3.reset();
|
||||||
|
CS(7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function PLF() {
|
||||||
|
if (NS) {
|
||||||
|
NS = false
|
||||||
|
IS(0)
|
||||||
|
UP()
|
||||||
|
music.playSoundEffect(sounds.animalsDogBark2)
|
||||||
|
control.timer4.reset()
|
||||||
|
GTO = Math.randomRange(4, 8);
|
||||||
|
}
|
||||||
|
if(PTC()) {
|
||||||
|
CS(0);
|
||||||
|
}
|
||||||
|
if (control.timer4.seconds() > GTO) {
|
||||||
|
music.playSoundEffect(sounds.animalsDogBark2)
|
||||||
|
control.timer4.reset();
|
||||||
|
GTO = Math.randomRange(4, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function NGR() {
|
||||||
|
NS = false
|
||||||
|
IS(4)
|
||||||
|
music.playSoundEffect(sounds.animalsDogGrowl);
|
||||||
|
UP();
|
||||||
|
loops.pause(1500);
|
||||||
|
music.stopAllSounds()
|
||||||
|
music.playSoundEffect(sounds.animalsDogBark1)
|
||||||
|
P_C--;
|
||||||
|
CS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function HNG() {
|
||||||
|
if (NS) {
|
||||||
|
NS = false;
|
||||||
|
IS(3)
|
||||||
|
DN();
|
||||||
|
music.playSoundEffect(sounds.animalsDogWhine);
|
||||||
|
}
|
||||||
|
if(FDC()) {
|
||||||
|
CS(0)
|
||||||
|
}
|
||||||
|
if (PTC()) {
|
||||||
|
CS(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function PPP() {
|
||||||
|
NS = false;
|
||||||
|
IS(2);
|
||||||
|
UP();
|
||||||
|
loops.pause(100)
|
||||||
|
motors.largeA.setSpeed(-30, 70, MoveUnit.Degrees);
|
||||||
|
loops.pause(800);
|
||||||
|
music.playSoundEffect(sounds.mechanicalHorn1);
|
||||||
|
loops.pause(1000);
|
||||||
|
for(let i = 0; i < 3; ++i) {
|
||||||
|
motors.largeA.setSpeed(-30, 20, MoveUnit.Degrees);
|
||||||
|
motors.largeA.setSpeed(30, 20, MoveUnit.Degrees);
|
||||||
|
}
|
||||||
|
motors.largeA.setSpeed(30, 70, MoveUnit.Degrees);
|
||||||
|
F_C = 1;
|
||||||
|
CS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function HPY() {
|
||||||
|
IS(8)
|
||||||
|
MHT(0);
|
||||||
|
motors.largeAD.setSpeed(10, 0.8, MoveUnit.Seconds);
|
||||||
|
for(let i = 0; i < 3; ++i) {
|
||||||
|
music.playSoundEffect(sounds.animalsDogBark1);
|
||||||
|
motors.largeAD.setSpeed(-100, 0.2, MoveUnit.Seconds);
|
||||||
|
loops.pause(300)
|
||||||
|
motors.largeAD.setSpeed(10, 0.3, MoveUnit.Seconds)
|
||||||
|
}
|
||||||
|
loops.pause(500);
|
||||||
|
music.stopAllSounds();
|
||||||
|
DN();
|
||||||
|
RST();
|
||||||
|
}
|
||||||
|
|
||||||
|
function STL() {
|
||||||
|
UP();
|
||||||
|
motors.largeAD.setSpeed(-20, 60, MoveUnit.Degrees);
|
||||||
|
music.playSoundEffect(sounds.animalsDogWhine);
|
||||||
|
motors.largeAD.setSpeed(20, 60, MoveUnit.Degrees);
|
||||||
|
}
|
||||||
|
|
||||||
|
function WKU() {
|
||||||
|
let stateC = false;
|
||||||
|
IS(5);
|
||||||
|
music.playSoundEffect(sounds.animalsDogWhine)
|
||||||
|
MHT(0)
|
||||||
|
DN()
|
||||||
|
STL()
|
||||||
|
loops.pause(1000);
|
||||||
|
UP()
|
||||||
|
CS(0;)
|
||||||
|
}
|
||||||
|
|
||||||
|
DN();
|
||||||
|
MNRH();
|
||||||
|
// compare button state???
|
||||||
|
IS(1);
|
||||||
|
UP();
|
||||||
|
RST();
|
||||||
|
loops.forever(function () {
|
||||||
|
MON();
|
||||||
|
switch (DB_S) {
|
||||||
|
case 0:
|
||||||
|
IDL();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
SLP();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
PLF();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
NGR();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
HNG();
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
PPP();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
HPY();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
WKU();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
51
docs/examples/core-set/robotarm-labview.md
Normal file
51
docs/examples/core-set/robotarm-labview.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Robot Arm
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function INI() {
|
||||||
|
motors.largeB.setBrake(true)
|
||||||
|
motors.largeC.setBrake(true)
|
||||||
|
motors.mediumA.setBrake(true)
|
||||||
|
motors.largeB.setSpeed(-50)
|
||||||
|
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||||
|
motors.largeB.stop();
|
||||||
|
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds);
|
||||||
|
motors.mediumA.setSpeed(-50, 90, MoveUnit.Degrees);
|
||||||
|
motors.largeC.setSpeed(50)
|
||||||
|
sensors.touch1.pauseUntil(TouchSensorEvent.Pressed);
|
||||||
|
motors.largeC.setSpeed(-50, 0.86, MoveUnit.Rotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
INI()
|
||||||
|
|
||||||
|
let down = false;
|
||||||
|
loops.forever(function () {
|
||||||
|
brick.showImage(images.informationQuestionMark)
|
||||||
|
brick.setLight(BrickLight.OrangePulse);
|
||||||
|
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
|
||||||
|
brick.setLight(BrickLight.Off)
|
||||||
|
music.playSoundEffect(sounds.mechanicalAirRelease)
|
||||||
|
brick.showImage(images.informationAccept)
|
||||||
|
if (down) {
|
||||||
|
brick.showImage(images.informationForward)
|
||||||
|
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
|
||||||
|
} else {
|
||||||
|
brick.showImage(images.informationBackward)
|
||||||
|
motors.largeC.setSpeed(-65, 0.85, MoveUnit.Rotations);
|
||||||
|
}
|
||||||
|
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees)
|
||||||
|
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds)
|
||||||
|
motors.largeB.setSpeed(-55)
|
||||||
|
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||||
|
motors.largeB.stop();
|
||||||
|
if (down) {
|
||||||
|
motors.largeC.setSpeed(-65, 0.86, MoveUnit.Rotations);
|
||||||
|
} else {
|
||||||
|
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
|
||||||
|
}
|
||||||
|
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees);
|
||||||
|
motors.mediumA.setSpeed(-30, 90, MoveUnit.Degrees);
|
||||||
|
motors.largeB.setSpeed(-55)
|
||||||
|
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||||
|
motors.largeB.stop()
|
||||||
|
})
|
||||||
|
```
|
51
docs/examples/crane-labview.md
Normal file
51
docs/examples/crane-labview.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Crane LabView
|
||||||
|
|
||||||
|
```blocks
|
||||||
|
function INI() {
|
||||||
|
motors.largeB.setBrake(true)
|
||||||
|
motors.largeC.setBrake(true)
|
||||||
|
motors.mediumA.setBrake(true)
|
||||||
|
motors.largeB.setSpeed(-50)
|
||||||
|
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||||
|
motors.largeB.stop();
|
||||||
|
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds);
|
||||||
|
motors.mediumA.setSpeed(-50, 90, MoveUnit.Degrees);
|
||||||
|
motors.largeC.setSpeed(50)
|
||||||
|
sensors.touch1.pauseUntil(TouchSensorEvent.Pressed);
|
||||||
|
motors.largeC.setSpeed(-50, 0.86, MoveUnit.Rotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
INI()
|
||||||
|
|
||||||
|
let down = false;
|
||||||
|
loops.forever(function () {
|
||||||
|
brick.showImage(images.informationQuestionMark)
|
||||||
|
brick.setLight(BrickLight.OrangePulse);
|
||||||
|
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
|
||||||
|
brick.setLight(BrickLight.Off)
|
||||||
|
music.playSoundEffect(sounds.mechanicalAirRelease)
|
||||||
|
brick.showImage(images.informationAccept)
|
||||||
|
if (down) {
|
||||||
|
brick.showImage(images.informationForward)
|
||||||
|
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
|
||||||
|
} else {
|
||||||
|
brick.showImage(images.informationBackward)
|
||||||
|
motors.largeC.setSpeed(-65, 0.85, MoveUnit.Rotations);
|
||||||
|
}
|
||||||
|
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees)
|
||||||
|
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds)
|
||||||
|
motors.largeB.setSpeed(-55)
|
||||||
|
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||||
|
motors.largeB.stop();
|
||||||
|
if (down) {
|
||||||
|
motors.largeC.setSpeed(-65, 0.86, MoveUnit.Rotations);
|
||||||
|
} else {
|
||||||
|
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
|
||||||
|
}
|
||||||
|
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees);
|
||||||
|
motors.mediumA.setSpeed(-30, 90, MoveUnit.Degrees);
|
||||||
|
motors.largeB.setSpeed(-55)
|
||||||
|
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||||
|
motors.largeB.stop()
|
||||||
|
})
|
||||||
|
```
|
215
docs/examples/gyro-boy-labview.md
Normal file
215
docs/examples/gyro-boy-labview.md
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
# Gyro Boy LabView
|
||||||
|
|
||||||
|
```blocks
|
||||||
|
let mSum = 0;
|
||||||
|
let mPos = 0;
|
||||||
|
let mSpd = 0;
|
||||||
|
let mD = 0;
|
||||||
|
let mDP1 = 0;
|
||||||
|
let mDP2 = 0;
|
||||||
|
let mDP3 = 0;
|
||||||
|
let Crdv = 0;
|
||||||
|
let cLo = 0;
|
||||||
|
let gAng = 0;
|
||||||
|
let ok = false;
|
||||||
|
let pwr = 0;
|
||||||
|
let Cstr = 0;
|
||||||
|
let Cdrv = 0;
|
||||||
|
let gMn = 0;
|
||||||
|
let gMx = 0;
|
||||||
|
let gSum = 0;
|
||||||
|
let gyro = 0;
|
||||||
|
let gOS = 0;
|
||||||
|
let gSpd = 0;
|
||||||
|
let tInt = 0.014;
|
||||||
|
let lpwr = 0
|
||||||
|
let rpwr = 0
|
||||||
|
let tStart = 0
|
||||||
|
let st = 0
|
||||||
|
let oldDr = 0
|
||||||
|
|
||||||
|
function RST() {
|
||||||
|
motors.largeA.reset()
|
||||||
|
motors.largeD.reset()
|
||||||
|
motors.largeA.setRegulated(false)
|
||||||
|
motors.largeD.setRegulated(false)
|
||||||
|
sensors.gyro2.reset()
|
||||||
|
sensors.gyro2.rate()
|
||||||
|
control.timer2.reset()
|
||||||
|
loops.pause(5000)
|
||||||
|
mSum = 0;
|
||||||
|
mPos = 0;
|
||||||
|
mD = 0;
|
||||||
|
mDP1 = 0;
|
||||||
|
mDP2 = 0;
|
||||||
|
mDP3 = 0;
|
||||||
|
Crdv = 0;
|
||||||
|
cLo = 0;
|
||||||
|
gAng = 0;
|
||||||
|
ok = false;
|
||||||
|
pwr = 0;
|
||||||
|
st = 0;
|
||||||
|
Cstr = 0;
|
||||||
|
Cdrv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function OS() {
|
||||||
|
// OSL
|
||||||
|
do {
|
||||||
|
gMn = 1000;
|
||||||
|
gMx = -100;
|
||||||
|
gSum = 0;
|
||||||
|
// gChk
|
||||||
|
for (let i = 0; i < 200; i++) {
|
||||||
|
gyro = sensors.gyro2.rate()
|
||||||
|
gSum = gyro;
|
||||||
|
gMx = Math.max(gMx, gyro)
|
||||||
|
gMn = Math.min(gMn, gyro)
|
||||||
|
loops.pause(4);
|
||||||
|
}
|
||||||
|
} while (gMx - gMn > 2);
|
||||||
|
gOS = gSum / 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GT() {
|
||||||
|
if (cLo == 0) {
|
||||||
|
tInt = 0.014;
|
||||||
|
control.timer1.reset();
|
||||||
|
} else {
|
||||||
|
tInt = control.timer1.seconds() / cLo;
|
||||||
|
}
|
||||||
|
cLo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GG() {
|
||||||
|
gyro = sensors.gyro2.rate();
|
||||||
|
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
|
||||||
|
gSpd = gyro - gOS;
|
||||||
|
gAng = gAng + tInt * gSpd;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GM() {
|
||||||
|
let temp = mSum
|
||||||
|
mSum = motors.largeD.angle() + motors.largeA.angle();
|
||||||
|
mD = mSum - temp;
|
||||||
|
mPos = mPos + mD;
|
||||||
|
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
|
||||||
|
mDP3 = mDP2;
|
||||||
|
mDP2 = mDP1;
|
||||||
|
mDP1 = mD;
|
||||||
|
}
|
||||||
|
|
||||||
|
function EQ() {
|
||||||
|
mPos = mPos - Cdrv * tInt;
|
||||||
|
pwr = (0.8 * gSpd + 15 * gAng) + (0.095 * mSpd + 0.13 * mPos) - 0.01 * Cdrv
|
||||||
|
if (pwr > 100) pwr = 100
|
||||||
|
else if (pwr < -100) pwr = -100
|
||||||
|
}
|
||||||
|
|
||||||
|
function cntrl() {
|
||||||
|
mPos = mPos - tInt * Cdrv
|
||||||
|
lpwr = (pwr + Cstr * 0.1)
|
||||||
|
rpwr = (pwr - Cstr * 0.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function CHK() {
|
||||||
|
if (Math.abs(pwr) < 100)
|
||||||
|
control.timer2.reset();
|
||||||
|
if (control.timer2.seconds() > 2) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// M
|
||||||
|
loops.forever(function () {
|
||||||
|
RST();
|
||||||
|
brick.showImage(images.eyesSleeping)
|
||||||
|
OS()
|
||||||
|
gAng = -0.25;
|
||||||
|
music.playSoundEffect(sounds.movementsSpeedUp)
|
||||||
|
brick.showImage(images.eyesAwake)
|
||||||
|
st = 1;
|
||||||
|
// BALANCE
|
||||||
|
while (!ok) {
|
||||||
|
GT();
|
||||||
|
let t1 = control.timer1.millis()
|
||||||
|
GG();
|
||||||
|
GM();
|
||||||
|
EQ();
|
||||||
|
cntrl();
|
||||||
|
motors.largeA.setSpeed(lpwr)
|
||||||
|
motors.largeD.setSpeed(rpwr)
|
||||||
|
CHK()
|
||||||
|
let t2 = control.timer1.millis();
|
||||||
|
let p = 5 - (t2 - t1);
|
||||||
|
loops.pause(Math.max(1, p))
|
||||||
|
}
|
||||||
|
motors.stopAllMotors()
|
||||||
|
st = 0;
|
||||||
|
brick.setLight(BrickLight.RedPulse);
|
||||||
|
brick.showImage(images.eyesKnockedOut)
|
||||||
|
music.playSoundEffect(sounds.movementsSpeedDown)
|
||||||
|
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
|
||||||
|
brick.setLight(BrickLight.Off);
|
||||||
|
})
|
||||||
|
|
||||||
|
// BHV
|
||||||
|
loops.forever(function () {
|
||||||
|
switch (st) {
|
||||||
|
case 0:
|
||||||
|
Cdrv = 0;
|
||||||
|
Cstr = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Cdrv = 40;
|
||||||
|
loops.pause(4000);
|
||||||
|
Cdrv = 0;
|
||||||
|
music.playTone(1000, 100);
|
||||||
|
st = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (sensors.color1.color()) {
|
||||||
|
case ColorSensorColor.Red:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cdrv = 0;
|
||||||
|
Cstr = 0;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.Green:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cdrv = 150;
|
||||||
|
Cstr = 0;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.Blue:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cstr = 70;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.Yellow:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cstr = -70;
|
||||||
|
break;
|
||||||
|
case ColorSensorColor.White:
|
||||||
|
music.playTone(2000, 100);
|
||||||
|
Cdrv = -75;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sensors.ultrasonic4.distance() < 25) {
|
||||||
|
Cstr = 0;
|
||||||
|
oldDr = Cdrv;
|
||||||
|
Cdrv = -10;
|
||||||
|
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
|
||||||
|
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
|
||||||
|
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
|
||||||
|
if (Math.randomRange(-1, 1) >= 1)
|
||||||
|
Cstr = 70;
|
||||||
|
else
|
||||||
|
Cstr = -70;
|
||||||
|
loops.pause(4000);
|
||||||
|
music.playTone(2000, 100)
|
||||||
|
Cstr = 0;
|
||||||
|
Cdrv = oldDr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
loops.pause(80);
|
||||||
|
})
|
||||||
|
```
|
109
docs/static/avatar.svg
vendored
Normal file
109
docs/static/avatar.svg
vendored
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1"
|
||||||
|
id="svg2" inkscape:version="0.91 r13725" sodipodi:docname="avatar.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32 32"
|
||||||
|
style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#303030;}
|
||||||
|
</style>
|
||||||
|
<sodipodi:namedview bordercolor="#666666" borderopacity="1" gridtolerance="10" guidetolerance="10" id="namedview15" inkscape:current-layer="svg2" inkscape:cx="16" inkscape:cy="16" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-height="661" inkscape:window-maximized="0" inkscape:window-width="997" inkscape:window-x="0" inkscape:window-y="0" inkscape:zoom="5.2149125" objecttolerance="10" pagecolor="#ffffff" showgrid="false">
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<g id="avatar_mf" transform="translate(-5304.979 8145.745)">
|
||||||
|
<path id="Path_180" class="st0" d="M5317.1-8125.6c0.2,0,0.3-0.1,0.5-0.1l2.9-0.6c1.3-0.3,2.5-0.5,3.8-0.8c0.5-0.1,1-0.2,1.5-0.3
|
||||||
|
c0.1,0,0.1,0,0.1-0.1c0-0.5,0-1-0.1-1.5c-0.1-0.6-0.2-1.1-0.3-1.7c-0.1-0.4-0.1-0.8-0.2-1.2c-0.1-0.7-0.2-1.4-0.3-2
|
||||||
|
c-0.1-0.6-0.2-1.1-0.3-1.7c0-0.2-0.2-0.4-0.4-0.4c0,0,0,0-0.1,0c-0.2,0-0.5,0.1-0.7,0.1c-0.5,0.1-1,0.1-1.5,0.2
|
||||||
|
c-0.5,0.1-1,0.1-1.6,0.2c-0.5,0.1-1,0.1-1.4,0.2c-0.2,0-0.3,0-0.5,0.1c-0.2,0-0.4,0.2-0.5,0.4c0,0.2-0.1,0.4-0.1,0.5
|
||||||
|
c0,0.4-0.1,0.8-0.1,1.2c-0.1,0.5-0.1,1-0.2,1.5c0,0.4-0.1,0.9-0.1,1.3l-0.1,1.3l-0.1,1.3c-0.1,0.5-0.1,1-0.2,1.5
|
||||||
|
C5317.1-8126,5317.1-8125.8,5317.1-8125.6z"/>
|
||||||
|
<path id="Path_181" class="st0" d="M5316.1-8140c0,0.6,0.1,1.2,0.1,1.8c0,0.4,0.2,0.8,0.6,1c0.3,0.2,0.7,0.3,1.1,0.3
|
||||||
|
c0.7,0.1,1.4,0.1,2.1,0c0.6,0,1.2-0.1,1.8-0.2c0.4,0,0.9-0.2,1.2-0.5c0.3-0.3,0.5-0.7,0.5-1.1c0-1.2,0-2.3-0.1-3.5
|
||||||
|
c0-0.3-0.1-0.6-0.3-0.8c-0.3-0.4-0.8-0.6-1.4-0.6c0,0,0,0-0.1,0c-0.2,0.1-0.4,0.1-0.6,0.1c-0.9,0-1.8,0.1-2.7,0.1
|
||||||
|
c-0.1,0-0.3,0-0.4,0c-0.4-0.1-0.8,0-1.2,0.2c-0.4,0.2-0.6,0.6-0.7,1c0,0.1,0,0.2,0,0.3C5316-8141.2,5316.1-8140.6,5316.1-8140
|
||||||
|
L5316.1-8140z"/>
|
||||||
|
<path id="Path_182" class="st0" d="M5312-8129.2c0,0.6,0,1.2,0,1.8c0,0.1,0,0.1,0.1,0.1c0.3,0,0.6,0.1,0.9,0.1c0.3,0,0.7,0,1,0
|
||||||
|
c0.1,0,0.2,0,0.3,0c0.1,0,0.1,0,0.1-0.1c0.1-0.4,0.2-0.8,0.2-1.2c0.1-0.5,0.2-1,0.3-1.4c0-0.1,0.1-0.1,0.1-0.1
|
||||||
|
c0.4-0.2,0.8-0.5,1.2-0.8c0.4-0.4,0.7-0.9,0.8-1.5c0.1-0.6,0-1.2-0.4-1.7c-0.2-0.3-0.6-0.4-0.9-0.3c-0.3,0.1-0.6,0.3-0.9,0.5
|
||||||
|
c-0.7,0.6-1.5,1.2-2.2,1.8c-0.3,0.2-0.5,0.5-0.6,0.8c0,0.2-0.1,0.4-0.1,0.6C5311.9-8130.2,5311.9-8129.7,5312-8129.2
|
||||||
|
C5311.9-8129.2,5312-8129.2,5312-8129.2z"/>
|
||||||
|
<path id="Path_183" class="st0" d="M5315.5-8124.7c0,0.2-0.1,0.5-0.1,0.7c-0.1,0.5-0.4,0.9-0.8,1.1c0,0,0,0,0,0
|
||||||
|
c-0.1,0-0.2,0.2-0.2,0.3c-0.4,1.4-0.9,2.7-1.3,4.1c0,0,0,0.1,0,0.1c0.8,1.1,1.6,2.2,2.4,3.3c0,0,0,0,0.1,0.1
|
||||||
|
c0.1-0.2,0.1-0.3,0.2-0.5c0.1-0.3,0.2-0.5,0.3-0.8c0,0,0-0.1,0-0.1c-0.2-0.3-0.5-0.7-0.7-1c0,0,0-0.1,0-0.2
|
||||||
|
c0.3-0.9,0.6-1.7,0.9-2.6c0,0,0-0.1,0.1-0.1c0.5-0.2,0.9-0.6,1.1-1.1c0.1-0.3,0.1-0.7,0.1-1.1c0-0.4-0.1-0.8-0.3-1.2
|
||||||
|
c-0.2-0.4-0.5-0.8-1-1C5315.9-8124.7,5315.7-8124.7,5315.5-8124.7z"/>
|
||||||
|
<path id="Path_184" class="st0" d="M5314.7-8134.2c0.1-0.1,0.2-0.1,0.3-0.2c0.3-0.2,0.7-0.3,1-0.3c0.4,0,0.7,0.2,0.8,0.6
|
||||||
|
c0.6,1.1,0.5,2.4-0.4,3.3c-0.4,0.4-0.8,0.7-1.3,1c0,0-0.1,0.1-0.1,0.1c-0.2,0.8-0.3,1.6-0.5,2.5c0,0,0,0.1,0,0.1
|
||||||
|
c0,0.2,0,0.2-0.2,0.2c-0.1,0-0.1,0-0.2,0c0,0.1,0,0.2,0,0.3c0,0,0,0,0.1,0.1l1.9,0.7c0.2,0.1,0.4,0.2,0.7,0.2c0-0.1,0-0.2,0-0.2
|
||||||
|
c0-0.3,0-0.6,0-0.8l0.2-1.5l0.2-1.5c0.1-0.5,0.1-1,0.2-1.5c0.1-0.5,0.1-1.1,0.2-1.6c0.1-0.5,0.1-1,0.2-1.5c0-0.2,0-0.4,0-0.6
|
||||||
|
c0-0.2-0.1-0.4-0.3-0.4c0,0,0,0,0,0c-0.1,0-0.1,0-0.2,0c-0.6-0.1-1.2-0.2-1.9-0.3c-0.1,0-0.2,0-0.3,0c-0.1,0-0.2,0.1-0.3,0.3
|
||||||
|
C5314.8-8135,5314.7-8134.6,5314.7-8134.2z"/>
|
||||||
|
<path id="Path_185" class="st0" d="M5324.5-8117.2c-0.2-0.7-0.5-1.3-0.7-2l-0.7,0.3c0,0-0.1,0-0.1,0c-0.1,0.1-0.2,0-0.2-0.1
|
||||||
|
c-0.1-0.3-0.2-0.5-0.3-0.8c-0.2-0.7-0.5-1.4-0.7-2.1c0,0,0-0.1,0-0.1c0,0,0,0.1-0.1,0.1c-0.1,0.2-0.3,0.3-0.5,0.5c0,0-0.1,0-0.1,0
|
||||||
|
c-0.3,0.1-0.6,0.1-0.8,0.2c0,0-0.1,0-0.1,0c0,0.2-0.1,0.3-0.1,0.5c0.6,1.5,1.1,3.1,1.7,4.6c0,0,0,0,0,0.1
|
||||||
|
C5322.7-8116.3,5323.6-8116.7,5324.5-8117.2z"/>
|
||||||
|
<path id="Path_186" class="st0" d="M5325.4-8123.1c-0.7,0.2-1.3,0.3-2,0.5c-0.5,0.1-0.9,0.2-1.4,0.3c-0.1,0-0.2,0.1-0.1,0.2
|
||||||
|
c0,0,0,0,0,0.1c0.2,0.5,0.3,0.9,0.5,1.4c0.2,0.5,0.4,1.1,0.6,1.6c0,0,0,0,0,0c0.1-0.1,0.2-0.1,0.3-0.2c0.2-0.1,0.3-0.2,0.5-0.2
|
||||||
|
c0.2-0.1,0.4-0.1,0.6-0.2c0.7-0.2,1.5-0.4,2.2-0.6c0,0,0,0,0.1,0C5326.3-8121.1,5325.9-8122.1,5325.4-8123.1z"/>
|
||||||
|
<path id="Path_187" class="st0" d="M5320.7-8124.4c-0.4,0.1-0.8,0.2-1.2,0.3c-0.6,0.1-1.3,0.3-1.9,0.4c0,0-0.1,0-0.1,0
|
||||||
|
c-0.1,0-0.2-0.1-0.3-0.1c0,0,0,0.1,0,0.1c0.3,0.7,0.4,1.5,0.3,2.2c-0.1,0.4-0.3,0.8-0.5,1.1c0,0,0,0-0.1,0.1
|
||||||
|
c0.2-0.1,0.4-0.1,0.6-0.1l2.5-0.6c0.5-0.1,0.9-0.6,1-1.1c0.1-0.5,0-1-0.1-1.5C5320.8-8124,5320.8-8124.2,5320.7-8124.4z"/>
|
||||||
|
<path id="Path_188" class="st0" d="M5325.5-8127c-2.7,0.5-5.3,1.1-7.9,1.6c0,0.5,0,0.9,0.1,1.4c0.1,0,0.2,0,0.3-0.1
|
||||||
|
c1.2-0.3,2.3-0.5,3.5-0.8c1.2-0.3,2.4-0.5,3.6-0.8c0.1,0,0.3-0.1,0.4-0.1c0,0,0.1,0,0.1-0.1
|
||||||
|
C5325.6-8126.2,5325.5-8126.6,5325.5-8127z"/>
|
||||||
|
<path id="Path_189" class="st0" d="M5328.6-8118.4c-0.2-0.4-0.3-0.7-0.5-1.1c-0.1-0.2-0.2-0.5-0.3-0.7c0-0.1,0-0.1-0.1,0
|
||||||
|
c-1.2,0.3-2.4,0.6-3.6,1c0,0,0,0-0.1,0c0.2,0.7,0.5,1.3,0.7,2C5326-8117.6,5327.3-8118,5328.6-8118.4z"/>
|
||||||
|
<path id="Path_190" class="st0" d="M5319.9-8120.9l-0.6,0.1c-1,0.2-2,0.5-3,0.7c-0.1,0-0.1,0.1-0.1,0.1c-0.3,0.7-0.5,1.5-0.8,2.2
|
||||||
|
c0,0,0,0,0,0.1c0.2,0,0.4-0.1,0.5-0.1c1-0.3,2-0.5,3.1-0.8c0.1,0,0.2-0.1,0.3-0.2C5319.5-8119.5,5319.7-8120.2,5319.9-8120.9z"/>
|
||||||
|
<path id="Path_191" class="st0" d="M5325.1-8125.4c-1.1,0.2-2.2,0.5-3.3,0.7c0.3,0.7,0.4,1.4,0.3,2.2c0.2,0,0.4-0.1,0.5-0.1
|
||||||
|
c0.9-0.2,1.8-0.4,2.7-0.6c0.1,0,0.1,0,0.1-0.1c0.1-0.4,0-0.9-0.1-1.3C5325.3-8124.9,5325.2-8125.1,5325.1-8125.4
|
||||||
|
C5325.1-8125.3,5325.1-8125.4,5325.1-8125.4z"/>
|
||||||
|
<path id="Path_192" class="st0" d="M5325.6-8132c0.2,0,0.4,0,0.5,0c0.2,0,0.4,0,0.6,0c0.3,0,0.6-0.2,0.8-0.4c0.3-0.4,0.7-0.8,1-1.2
|
||||||
|
c-0.1-0.1-0.1-0.1-0.1-0.2c0,0,0,0-0.1,0c-0.7-0.1-1.3-0.5-1.4-1.2c-0.1-0.2-0.1-0.4-0.1-0.6c-0.2,0.1-0.3,0.3-0.5,0.4
|
||||||
|
c-0.1,0.1-0.2,0.1-0.3,0.2c0,0-0.1,0.1-0.2,0c-0.2,0-0.5-0.1-0.7-0.1c0,0,0,0-0.1,0C5325.3-8134.1,5325.4-8133.1,5325.6-8132z"/>
|
||||||
|
<path id="Path_193" class="st0" d="M5328.4-8134.2c0.2-0.3,0.5-0.5,0.8-0.7c0.4-0.4,0.6-0.8,0.7-1.4c0-0.1,0-0.2-0.1-0.3
|
||||||
|
c-0.3-0.5-0.7-1.1-1-1.6c0-0.1-0.1-0.1-0.1,0c-0.4,0.2-0.8,0.5-1.1,0.8c-0.2,0.2-0.4,0.4-0.6,0.6c-0.1,0.1-0.1,0.3,0,0.4
|
||||||
|
c0.5,0.7,1,1.5,1.4,2.2C5328.4-8134.2,5328.4-8134.2,5328.4-8134.2z"/>
|
||||||
|
<path id="Path_194" class="st0" d="M5314.3-8126.1c-0.1-0.1-0.1-0.1-0.2-0.2c-0.1,0-0.1-0.1-0.1-0.2c0-0.1,0-0.3,0-0.4h-0.1
|
||||||
|
c-0.6,0-1.2-0.1-1.7-0.2c0,0-0.1,0-0.1,0c-0.4,0.2-0.7,0.4-1,0.8c-0.4,0.6-0.4,1.4,0.1,1.9c0.2,0.2,0.4,0.4,0.6,0.6
|
||||||
|
c0.1,0.1,0.2,0.2,0.3,0.2c-0.2-0.6,0-1.3,0.5-1.8C5313-8125.9,5313.6-8126.2,5314.3-8126.1z"/>
|
||||||
|
<path id="Path_195" class="st0" d="M5315.7-8114.9c0.5-0.1,0.9-0.3,1.4-0.4c0.8-0.2,1.6-0.4,2.4-0.7c0.1,0,0.1,0,0.1-0.1
|
||||||
|
c0.1-0.4,0.2-0.7,0.4-1.1c0,0,0,0,0-0.1c-0.1,0-0.2,0-0.3,0.1c-1.2,0.3-2.3,0.6-3.5,1c-0.1,0-0.1,0.1-0.1,0.1
|
||||||
|
c-0.1,0.4-0.3,0.7-0.4,1.1C5315.7-8115,5315.7-8115,5315.7-8114.9z"/>
|
||||||
|
<path id="Path_196" class="st0" d="M5315.4-8117.4c0.2,0.3,0.4,0.6,0.6,0.9c0,0,0.1,0,0.1,0c1-0.3,1.9-0.5,2.9-0.8
|
||||||
|
c0.3-0.1,0.6-0.2,0.9-0.2c-0.1-0.1-0.1-0.2-0.2-0.2c-0.2-0.2-0.3-0.4-0.5-0.6c0,0-0.1-0.1-0.1,0c-0.9,0.3-1.9,0.5-2.8,0.8
|
||||||
|
C5316-8117.5,5315.7-8117.5,5315.4-8117.4z"/>
|
||||||
|
<path id="Path_197" class="st0" d="M5321.3-8143.6c0-0.3,0-0.7,0-1c0,0-0.1,0-0.1,0c-0.7,0-1.5,0-2.2,0.1c-0.4,0-0.7,0-1.1,0.1
|
||||||
|
c-0.1,0-0.1,0-0.1,0.1c0,0.3,0,0.6,0,0.8c0,0,0,0.1,0.1,0.1c0.4,0,0.8,0,1.1,0c0.5,0,1.1,0,1.6-0.1
|
||||||
|
C5320.9-8143.5,5321.1-8143.6,5321.3-8143.6z"/>
|
||||||
|
<path id="Path_198" class="st0" d="M5329.2-8134.3c0.1,0,0.2,0,0.2-0.1c0.4-0.2,0.8-0.4,1.1-0.7c0.3-0.2,0.4-0.5,0.6-0.8
|
||||||
|
c0.1-0.3,0.1-0.6-0.1-0.9c-0.4-0.5-0.7-1-1.1-1.6c0,0,0,0-0.1-0.1c-0.2,0.2-0.4,0.4-0.6,0.6c0,0,0,0,0,0c0,0,0,0.1,0,0.1
|
||||||
|
c0.2,0.4,0.5,0.7,0.7,1c0.1,0.2,0.2,0.4,0.1,0.6c0,0.5-0.1,0.9-0.4,1.3c-0.1,0.1-0.2,0.2-0.3,0.3
|
||||||
|
C5329.4-8134.5,5329.3-8134.4,5329.2-8134.3C5329.2-8134.3,5329.2-8134.3,5329.2-8134.3z"/>
|
||||||
|
<path id="Path_199" class="st0" d="M5317.5-8136.7c0,0.2,0,0.3,0,0.5c0,0,0,0.1,0.1,0.1c0.2,0,0.3,0.1,0.5,0.1c0.7,0.1,1.4,0.1,2,0
|
||||||
|
c0.4,0,0.8-0.1,1.2-0.1c0.2,0,0.5-0.1,0.7-0.1c0.1,0,0.1,0,0.1-0.1c0-0.2,0-0.3,0-0.5C5320.5-8136.6,5319-8136.5,5317.5-8136.7z"/>
|
||||||
|
<path id="Path_200" class="st0" d="M5312.5-8123.2c0.1-0.4,0.1-0.8,0.2-1.2c0.1-0.6,0.6-1,1.2-1c0.3,0,0.5,0.1,0.7,0.3
|
||||||
|
c0.2,0.2,0.2,0.4,0.2,0.7c-0.1,0.3-0.2,0.6-0.2,0.9c0,0.1-0.1,0.2-0.1,0.4c0,0,0,0,0,0c0.1-0.1,0.2-0.2,0.3-0.3
|
||||||
|
c0.3-0.4,0.4-0.9,0.4-1.4c0-0.6-0.4-1-0.9-1.1c-0.1,0-0.1,0-0.2,0c-0.5,0-1,0.3-1.4,0.7c-0.3,0.3-0.4,0.6-0.5,1
|
||||||
|
c-0.1,0.3,0,0.7,0.2,1C5312.5-8123.2,5312.5-8123.2,5312.5-8123.2z"/>
|
||||||
|
<path id="Path_201" class="st0" d="M5314.3-8123.2c0.1-0.5,0.3-0.9,0.4-1.4c0.1-0.2,0-0.4-0.2-0.5c-0.4-0.2-0.9-0.1-1.2,0.2
|
||||||
|
c0,0,0,0,0,0.1c0,0.2,0,0.4,0.1,0.6c0,0.1,0.1,0.2,0.2,0.3C5313.7-8123.6,5314-8123.4,5314.3-8123.2
|
||||||
|
C5314.2-8123.2,5314.3-8123.2,5314.3-8123.2z"/>
|
||||||
|
<path id="Path_202" class="st0" d="M5317.4-8124.1c0-0.4,0-0.9-0.1-1.3c-0.1,0-0.1,0-0.2,0c-0.1,0-0.2,0-0.3,0
|
||||||
|
c-0.7-0.3-1.4-0.5-2.1-0.8c0,0,0,0,0,0c0.1,0.1,0.1,0.1,0.2,0.2c0.3,0.2,0.5,0.6,0.6,0.9c0,0,0,0,0,0c0.1,0,0.3,0,0.4,0.1
|
||||||
|
c0.3,0.1,0.6,0.3,0.9,0.5c0,0,0.1,0.1,0.1,0.1C5317.1-8124.2,5317.2-8124.1,5317.4-8124.1z"/>
|
||||||
|
<path id="Path_203" class="st0" d="M5321.6-8124.6c-0.2,0-0.4,0.1-0.6,0.1c0.1,0.2,0.1,0.4,0.2,0.6c0.1,0.4,0.2,0.8,0.1,1.2
|
||||||
|
c0,0.5-0.1,0.9-0.4,1.3c0,0,0,0,0,0c0.3,0,0.6-0.2,0.7-0.5c0.2-0.3,0.3-0.6,0.3-0.9C5321.9-8123.4,5321.8-8124,5321.6-8124.6z"/>
|
||||||
|
<path id="Path_204" class="st0" d="M5315.7-8135.8c0.2,0,0.3,0.1,0.5,0.1c0.5,0.1,1,0.2,1.5,0.2c0.2,0,0.5,0,0.7,0
|
||||||
|
c0.7-0.1,1.4-0.2,2.1-0.2c0.6-0.1,1.2-0.2,1.8-0.2c0.5-0.1,1.1-0.1,1.6-0.2l-1.5-0.2c0,0,0,0,0,0c0,0.2-0.1,0.3-0.2,0.3
|
||||||
|
c0,0,0,0,0,0c-0.3,0.1-0.5,0.1-0.8,0.2c-0.8,0.1-1.6,0.1-2.3,0.1c-0.4,0-0.9,0-1.3-0.1c-0.1,0-0.2-0.1-0.3-0.2c0,0-0.1,0-0.1,0
|
||||||
|
c-0.3,0-0.6,0.1-0.9,0.1L5315.7-8135.8L5315.7-8135.8z"/>
|
||||||
|
<path id="Path_205" class="st0" d="M5327.3-8117.7c-0.3,0.1-0.5,0.2-0.8,0.2c-0.6,0.2-1.1,0.3-1.7,0.5c0,0-0.1,0-0.1,0.1
|
||||||
|
c-0.5,0.2-1,0.5-1.5,0.7c0,0,0,0,0,0c0.3-0.1,0.5-0.1,0.8-0.2c0.5-0.2,1.1-0.3,1.6-0.5c0.1,0,0.2-0.1,0.2-0.1
|
||||||
|
C5326.2-8117.2,5326.8-8117.5,5327.3-8117.7C5327.3-8117.7,5327.3-8117.7,5327.3-8117.7C5327.3-8117.7,5327.3-8117.7,5327.3-8117.7
|
||||||
|
z"/>
|
||||||
|
<path id="Path_206" class="st0" d="M5327-8135.8c0,0.1,0,0.2,0,0.4c0.1,0.5,0.3,0.9,0.7,1.1c0.1,0.1,0.3,0.1,0.4,0.2l0,0
|
||||||
|
C5327.8-8134.7,5327.4-8135.2,5327-8135.8L5327-8135.8z"/>
|
||||||
|
<path id="Path_207" class="st0" d="M5329-8134.4c-0.1,0.1-0.2,0.2-0.3,0.4c0,0,0,0,0,0.1c0,0.1,0,0.1,0.1,0.1c0.1,0,0.2,0,0.3-0.1
|
||||||
|
c0.1,0,0.2-0.1,0.3-0.1c-0.1,0-0.1-0.1-0.2-0.1C5329-8134.2,5329-8134.3,5329-8134.4z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 11 KiB |
@ -4,10 +4,11 @@
|
|||||||
import { deployCoreAsync, initAsync } from "./deploy";
|
import { deployCoreAsync, initAsync } from "./deploy";
|
||||||
import { FieldPorts } from "./field_ports";
|
import { FieldPorts } from "./field_ports";
|
||||||
import { FieldImages } from "./field_images";
|
import { FieldImages } from "./field_images";
|
||||||
import {FieldSpeed} from "./field_speed";
|
import { FieldSpeed } from "./field_speed";
|
||||||
import { FieldBrickButtons } from "./field_brickbuttons";
|
import { FieldBrickButtons } from "./field_brickbuttons";
|
||||||
|
import { FieldTurnRatio } from "./field_turnratio";
|
||||||
|
|
||||||
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
pxt.editor.initExtensionsAsync = function(opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
||||||
pxt.debug('loading pxt-ev3 target extensions...')
|
pxt.debug('loading pxt-ev3 target extensions...')
|
||||||
updateBlocklyShape();
|
updateBlocklyShape();
|
||||||
const res: pxt.editor.ExtensionResult = {
|
const res: pxt.editor.ExtensionResult = {
|
||||||
@ -23,6 +24,9 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
|
|||||||
}, {
|
}, {
|
||||||
selector: "brickbuttons",
|
selector: "brickbuttons",
|
||||||
editor: FieldBrickButtons
|
editor: FieldBrickButtons
|
||||||
|
}, {
|
||||||
|
selector: "turnratio",
|
||||||
|
editor: FieldTurnRatio
|
||||||
}],
|
}],
|
||||||
deployCoreAsync
|
deployCoreAsync
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,9 @@ export class FieldPorts extends Blockly.FieldDropdown implements Blockly.FieldCu
|
|||||||
this.width_ = parseInt(options.width) || 300;
|
this.width_ = parseInt(options.width) || 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trimOptions_() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a dropdown menu under the text.
|
* Create a dropdown menu under the text.
|
||||||
* @private
|
* @private
|
||||||
@ -42,7 +45,8 @@ export class FieldPorts extends Blockly.FieldDropdown implements Blockly.FieldCu
|
|||||||
// Accessibility properties
|
// Accessibility properties
|
||||||
contentDiv.setAttribute('role', 'menu');
|
contentDiv.setAttribute('role', 'menu');
|
||||||
contentDiv.setAttribute('aria-haspopup', 'true');
|
contentDiv.setAttribute('aria-haspopup', 'true');
|
||||||
const options = this.getOptions();
|
let options = this.getOptions();
|
||||||
|
options = options.sort();
|
||||||
for (let i = 0, option: any; option = options[i]; i++) {
|
for (let i = 0, option: any; option = options[i]; i++) {
|
||||||
let content = (options[i] as any)[0]; // Human-readable text or image.
|
let content = (options[i] as any)[0]; // Human-readable text or image.
|
||||||
const value = (options[i] as any)[1]; // Language-neutral value.
|
const value = (options[i] as any)[1]; // Language-neutral value.
|
||||||
|
108
editor/field_turnratio.ts
Normal file
108
editor/field_turnratio.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
|
||||||
|
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||||
|
|
||||||
|
export interface FieldTurnRatioOptions extends Blockly.FieldCustomOptions {
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.FieldCustom {
|
||||||
|
public isFieldCustom_ = true;
|
||||||
|
|
||||||
|
private params: any;
|
||||||
|
|
||||||
|
private path_: SVGPathElement;
|
||||||
|
private reporter_: SVGTextElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for a color wheel field.
|
||||||
|
* @param {number|string} value The initial content of the field.
|
||||||
|
* @param {Function=} opt_validator An optional function that is called
|
||||||
|
* to validate any constraints on what the user entered. Takes the new
|
||||||
|
* text as an argument and returns either the accepted text, a replacement
|
||||||
|
* text, or null to abort the change.
|
||||||
|
* @extends {Blockly.FieldNumber}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
constructor(value_: any, params: FieldTurnRatioOptions, opt_validator?: Function) {
|
||||||
|
super(String(value_), '-100', '100', null, '10', 'TurnRatio', opt_validator);
|
||||||
|
this.params = params;
|
||||||
|
(this as any).sliderColor_ = '#a8aaa8';
|
||||||
|
}
|
||||||
|
|
||||||
|
static HALF = 80;
|
||||||
|
static HANDLE_RADIUS = 30;
|
||||||
|
static RADIUS = FieldTurnRatio.HALF - FieldTurnRatio.HANDLE_RADIUS - 1;
|
||||||
|
|
||||||
|
createLabelDom_(labelText: string) {
|
||||||
|
let labelContainer = document.createElement('div');
|
||||||
|
let svg = Blockly.utils.createSvgElement('svg', {
|
||||||
|
'xmlns': 'http://www.w3.org/2000/svg',
|
||||||
|
'xmlns:html': 'http://www.w3.org/1999/xhtml',
|
||||||
|
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
|
||||||
|
'version': '1.1',
|
||||||
|
'height': (FieldTurnRatio.HALF + FieldTurnRatio.HANDLE_RADIUS + 10) + 'px',
|
||||||
|
'width': (FieldTurnRatio.HALF * 2) + 'px'
|
||||||
|
}, labelContainer);
|
||||||
|
let defs = Blockly.utils.createSvgElement('defs', {}, svg);
|
||||||
|
let marker = Blockly.utils.createSvgElement('marker', {
|
||||||
|
'id': 'head',
|
||||||
|
'orient': "auto",
|
||||||
|
'markerWidth': '2',
|
||||||
|
'markerHeight': '4',
|
||||||
|
'refX': '0.1', 'refY': '1.5'
|
||||||
|
}, defs);
|
||||||
|
let markerPath = Blockly.utils.createSvgElement('path', {
|
||||||
|
'd': 'M0,0 V3 L1.5,1.5 Z',
|
||||||
|
'fill': '#f12a21'
|
||||||
|
}, marker);
|
||||||
|
this.reporter_ = pxsim.svg.child(svg, "text", {
|
||||||
|
'x': FieldTurnRatio.HALF, 'y': 96,
|
||||||
|
'text-anchor': 'middle', 'alignment-baseline': 'middle',
|
||||||
|
'style': 'font-size: 50px',
|
||||||
|
'class': 'sim-text inverted number'
|
||||||
|
}) as SVGTextElement;
|
||||||
|
this.path_ = Blockly.utils.createSvgElement('path', {
|
||||||
|
'x1': FieldTurnRatio.HALF,
|
||||||
|
'y1': FieldTurnRatio.HALF,
|
||||||
|
'marker-end': 'url(#head)',
|
||||||
|
'style': 'fill: none; stroke: #f12a21; stroke-width: 10'
|
||||||
|
}, svg);
|
||||||
|
this.updateGraph_();
|
||||||
|
let readout = document.createElement('span');
|
||||||
|
readout.setAttribute('class', 'blocklyFieldSliderReadout');
|
||||||
|
return [labelContainer, readout];
|
||||||
|
};
|
||||||
|
|
||||||
|
updateGraph_() {
|
||||||
|
if (!this.path_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let v = goog.math.clamp(parseFloat(this.getText()), -100, 100);
|
||||||
|
if (isNaN(v)) {
|
||||||
|
v = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = goog.math.clamp(parseFloat(this.getText()), -100, 100) / 100;
|
||||||
|
const theta = x * Math.PI / 2;
|
||||||
|
const cx = FieldTurnRatio.HALF;
|
||||||
|
const cy = FieldTurnRatio.HALF - 14;
|
||||||
|
const gamma = Math.PI - 2 * theta;
|
||||||
|
const r = FieldTurnRatio.RADIUS;
|
||||||
|
const alpha = 0.2 + Math.abs(x) * 0.5;
|
||||||
|
const x1 = 0;
|
||||||
|
const y1 = r * alpha;
|
||||||
|
const y2 = r * Math.sin(Math.PI / 2 - theta);
|
||||||
|
const x2 = r * Math.cos(Math.PI / 2 - theta);
|
||||||
|
const y3 = y2 - r * alpha * Math.cos(2 * theta);
|
||||||
|
const x3 = x2 - r * alpha * Math.sin(2 * theta);
|
||||||
|
|
||||||
|
|
||||||
|
const d = `M ${cx} ${cy} C ${cx} ${cy - y1} ${cx + x3} ${cy - y3} ${cx + x2} ${cy - y2}`;
|
||||||
|
this.path_.setAttribute('d', d);
|
||||||
|
|
||||||
|
this.reporter_.textContent = `${v}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
setReadout_(readout: Element, value: string) {
|
||||||
|
this.updateGraph_();
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,9 @@
|
|||||||
{
|
{
|
||||||
"chassis.Chassis": "A differential drive robot",
|
"chassis.Chassis": "A differential drive robot",
|
||||||
"chassis.Chassis.drive": "Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)\nusing a unicycle model.",
|
"chassis.Chassis.drive": "Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)\nusing a unicycle model.",
|
||||||
"chassis.Chassis.driveFor": "Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)\nusing a unicycle model.",
|
|
||||||
"chassis.Chassis.driveFor|param|rotationSpeed": "rotation of the robot around the center point, eg: 30",
|
|
||||||
"chassis.Chassis.driveFor|param|speed": "speed of the center point between motors, eg: 10",
|
|
||||||
"chassis.Chassis.driveFor|param|value": "the amount of movement, eg: 2",
|
|
||||||
"chassis.Chassis.drive|param|rotationSpeed": "rotation of the robot around the center point, eg: 30",
|
"chassis.Chassis.drive|param|rotationSpeed": "rotation of the robot around the center point, eg: 30",
|
||||||
"chassis.Chassis.drive|param|speed": "speed of the center point between motors, eg: 10",
|
"chassis.Chassis.drive|param|speed": "speed of the center point between motors, eg: 10",
|
||||||
|
"chassis.Chassis.drive|param|value": "the amount of movement, eg: 2",
|
||||||
"chassis.Chassis.setMotors": "Sets the motors used by the chassis, default is B+C",
|
"chassis.Chassis.setMotors": "Sets the motors used by the chassis, default is B+C",
|
||||||
"chassis.Chassis.setProperty": "Sets a property of the robot",
|
"chassis.Chassis.setProperty": "Sets a property of the robot",
|
||||||
"chassis.Chassis.setProperty|param|property": "the property to set",
|
"chassis.Chassis.setProperty|param|property": "the property to set",
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ChassisProperty.BaseLength|block": "base length (cm)",
|
"ChassisProperty.BaseLength|block": "base length (cm)",
|
||||||
"ChassisProperty.WheelRadius|block": "wheel radius (cm)",
|
"ChassisProperty.WheelRadius|block": "wheel radius (cm)",
|
||||||
"chassis.Chassis.driveFor|block": "drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s|for %value|%unit",
|
|
||||||
"chassis.Chassis.drive|block": "drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s",
|
"chassis.Chassis.drive|block": "drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s",
|
||||||
"chassis.Chassis.setMotors|block": "set %chassis|motors to %motors",
|
"chassis.Chassis.setMotors|block": "set %chassis|motors to %motors",
|
||||||
"chassis.Chassis.setProperty|block": "set %chassis|%property|to %value",
|
"chassis.Chassis.setProperty|block": "set %chassis|%property|to %value",
|
||||||
|
@ -24,19 +24,6 @@ namespace chassis {
|
|||||||
this.baseLength = 12;
|
this.baseLength = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)
|
|
||||||
* using a unicycle model.
|
|
||||||
* @param speed speed of the center point between motors, eg: 10
|
|
||||||
* @param rotationSpeed rotation of the robot around the center point, eg: 30
|
|
||||||
*/
|
|
||||||
//% blockId=motorDrive block="drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s"
|
|
||||||
//% inlineInputMode=inline
|
|
||||||
//% weight=99 blockGap=8
|
|
||||||
drive(speed: number, rotationSpeed: number) {
|
|
||||||
this.driveFor(speed, rotationSpeed, 0, MoveUnit.Degrees);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)
|
* Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)
|
||||||
* using a unicycle model.
|
* using a unicycle model.
|
||||||
@ -45,10 +32,10 @@ namespace chassis {
|
|||||||
* @param value the amount of movement, eg: 2
|
* @param value the amount of movement, eg: 2
|
||||||
* @param unit
|
* @param unit
|
||||||
*/
|
*/
|
||||||
//% blockId=motorDriveFor block="drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s|for %value|%unit"
|
//% blockId=motorDrive block="drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s"
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
//% weight=95 blockGap=8
|
//% weight=95 blockGap=8
|
||||||
driveFor(speed: number, rotationSpeed: number, value: number, unit: MoveUnit) {
|
drive(speed: number, rotationSpeed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
||||||
// speed is expressed in %
|
// speed is expressed in %
|
||||||
const R = this.wheelRadius; // cm
|
const R = this.wheelRadius; // cm
|
||||||
const L = this.baseLength; // cm
|
const L = this.baseLength; // cm
|
||||||
@ -65,7 +52,7 @@ namespace chassis {
|
|||||||
const sr = vr / maxw * 100; // %
|
const sr = vr / maxw * 100; // %
|
||||||
const sl = vl / maxw * 100; // %
|
const sl = vl / maxw * 100; // %
|
||||||
|
|
||||||
this.motors.tankFor(sr, sl, value, unit)
|
this.motors.tank(sr, sl, value, unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,5 +11,8 @@
|
|||||||
"sensors.ColorSensor.onLightChanged|param|handler": "the code to run when detected",
|
"sensors.ColorSensor.onLightChanged|param|handler": "the code to run when detected",
|
||||||
"sensors.ColorSensor.pauseForColor": "Waits for the given color to be detected",
|
"sensors.ColorSensor.pauseForColor": "Waits for the given color to be detected",
|
||||||
"sensors.ColorSensor.pauseForColor|param|color": "the color to detect",
|
"sensors.ColorSensor.pauseForColor|param|color": "the color to detect",
|
||||||
"sensors.ColorSensor.pauseForLight": "Waits for the given color to be detected"
|
"sensors.ColorSensor.pauseForLight": "Waits for the given color to be detected",
|
||||||
|
"sensors.ColorSensor.setThreshold": "Sets a threshold value",
|
||||||
|
"sensors.ColorSensor.setThreshold|param|condition": "the dark or bright light condition",
|
||||||
|
"sensors.ColorSensor.setThreshold|param|value": "the value threshold"
|
||||||
}
|
}
|
@ -19,11 +19,13 @@
|
|||||||
"sensors.ColorSensor.onLightChanged|block": "on %sensor|%mode|%condition",
|
"sensors.ColorSensor.onLightChanged|block": "on %sensor|%mode|%condition",
|
||||||
"sensors.ColorSensor.pauseForColor|block": "pause %sensor|for color %color",
|
"sensors.ColorSensor.pauseForColor|block": "pause %sensor|for color %color",
|
||||||
"sensors.ColorSensor.pauseForLight|block": "pause %sensor|for %mode|%condition",
|
"sensors.ColorSensor.pauseForLight|block": "pause %sensor|for %mode|%condition",
|
||||||
|
"sensors.ColorSensor.setThreshold|block": "set %sensor|%condition|to %value",
|
||||||
"sensors.color1|block": "color 1",
|
"sensors.color1|block": "color 1",
|
||||||
"sensors.color2|block": "color 2",
|
"sensors.color2|block": "color 2",
|
||||||
"sensors.color3|block": "color 3",
|
"sensors.color3|block": "color 3",
|
||||||
"sensors.color4|block": "color 4",
|
"sensors.color4|block": "color 4",
|
||||||
"sensors|block": "sensors",
|
"sensors|block": "sensors",
|
||||||
"{id:category}Sensors": "Sensors",
|
"{id:category}Sensors": "Sensors",
|
||||||
"{id:group}Color Sensor": "Color Sensor"
|
"{id:group}Color Sensor": "Color Sensor",
|
||||||
|
"{id:group}Threshold": "Threshold"
|
||||||
}
|
}
|
@ -152,7 +152,7 @@ namespace sensors {
|
|||||||
//% parts="colorsensor"
|
//% parts="colorsensor"
|
||||||
//% blockNamespace=sensors
|
//% blockNamespace=sensors
|
||||||
//% sensor.fieldEditor="ports"
|
//% sensor.fieldEditor="ports"
|
||||||
//% weight=99
|
//% weight=98
|
||||||
//% group="Color Sensor"
|
//% group="Color Sensor"
|
||||||
color(): ColorSensorColor {
|
color(): ColorSensorColor {
|
||||||
this.setMode(ColorSensorMode.Color)
|
this.setMode(ColorSensorMode.Color)
|
||||||
@ -221,6 +221,21 @@ namespace sensors {
|
|||||||
reflectedLight() {
|
reflectedLight() {
|
||||||
return this.light(LightIntensityMode.Reflected);
|
return this.light(LightIntensityMode.Reflected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a threshold value
|
||||||
|
* @param condition the dark or bright light condition
|
||||||
|
* @param value the value threshold
|
||||||
|
*/
|
||||||
|
//% blockId=colorSetThreshold block="set %sensor|%condition|to %value"
|
||||||
|
//% group="Threshold" blockGap=8 weight=90
|
||||||
|
//% value.min=0 value.max=100
|
||||||
|
setThreshold(condition: LightCondition, value: number) {
|
||||||
|
if (condition == LightCondition.Dark)
|
||||||
|
this.thresholdDetector.setLowThreshold(value)
|
||||||
|
else
|
||||||
|
this.thresholdDetector.setHighThreshold(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//% whenUsed block="color 3" weight=90 fixedInstance jres=icons.port3
|
//% whenUsed block="color 3" weight=90 fixedInstance jres=icons.port3
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"BrickLight": "Patterns for lights under the buttons.",
|
||||||
"ButtonEvent": "User interaction on buttons",
|
"ButtonEvent": "User interaction on buttons",
|
||||||
"Draw": "Drawing modes",
|
"Draw": "Drawing modes",
|
||||||
"Image.buffer": "Returns the underlaying Buffer object.",
|
"Image.buffer": "Returns the underlaying Buffer object.",
|
||||||
@ -6,14 +7,15 @@
|
|||||||
"Image.draw": "Draw an image on the screen.",
|
"Image.draw": "Draw an image on the screen.",
|
||||||
"Image.height": "Returns the height of an image.",
|
"Image.height": "Returns the height of an image.",
|
||||||
"Image.width": "Returns the width of an image.",
|
"Image.width": "Returns the width of an image.",
|
||||||
"LightsPattern": "Patterns for lights under the buttons.",
|
|
||||||
"MMap.getNumber": "Read a number in specified format from the buffer.",
|
"MMap.getNumber": "Read a number in specified format from the buffer.",
|
||||||
"MMap.ioctl": "Perform ioctl(2) on the underlaying file",
|
"MMap.ioctl": "Perform ioctl(2) on the underlaying file",
|
||||||
"MMap.length": "Returns the length of a Buffer object.",
|
"MMap.length": "Returns the length of a Buffer object.",
|
||||||
|
"MMap.lseek": "Set pointer on the underlaying file.",
|
||||||
"MMap.read": "Perform read(2) on the underlaying file",
|
"MMap.read": "Perform read(2) on the underlaying file",
|
||||||
"MMap.setNumber": "Write a number in specified format in the buffer.",
|
"MMap.setNumber": "Write a number in specified format in the buffer.",
|
||||||
"MMap.slice": "Read a range of bytes into a buffer.",
|
"MMap.slice": "Read a range of bytes into a buffer.",
|
||||||
"MMap.write": "Perform write(2) on the underlaying file",
|
"MMap.write": "Perform write(2) on the underlaying file",
|
||||||
|
"SeekWhence": "Mode for lseek()",
|
||||||
"brick.Button": "Generic button class, for device buttons and sensors.",
|
"brick.Button": "Generic button class, for device buttons and sensors.",
|
||||||
"brick.Button.isPressed": "Check if button is currently pressed or not.",
|
"brick.Button.isPressed": "Check if button is currently pressed or not.",
|
||||||
"brick.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
|
"brick.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
|
||||||
@ -28,11 +30,9 @@
|
|||||||
"brick.buttonRight": "Right button on the EV3 Brick.",
|
"brick.buttonRight": "Right button on the EV3 Brick.",
|
||||||
"brick.buttonUp": "Up button on the EV3 Brick.",
|
"brick.buttonUp": "Up button on the EV3 Brick.",
|
||||||
"brick.clearScreen": "Clears the screen",
|
"brick.clearScreen": "Clears the screen",
|
||||||
"brick.lightPattern": "Pattern block.",
|
|
||||||
"brick.lightPattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
|
|
||||||
"brick.printPorts": "Prints the port states on the screen",
|
"brick.printPorts": "Prints the port states on the screen",
|
||||||
"brick.setLight": "Set lights.",
|
"brick.setLight": "Set lights.",
|
||||||
"brick.setLight|param|pattern": "the lights pattern to use.",
|
"brick.setLight|param|pattern": "the lights pattern to use. eg: BrickLight.Orange",
|
||||||
"brick.showImage": "Shows an image on screen",
|
"brick.showImage": "Shows an image on screen",
|
||||||
"brick.showImage|param|image": "image to draw",
|
"brick.showImage|param|image": "image to draw",
|
||||||
"brick.showNumber": "Shows a number on the screen",
|
"brick.showNumber": "Shows a number on the screen",
|
||||||
@ -52,6 +52,12 @@
|
|||||||
"console.logValue|param|value": "to write",
|
"console.logValue|param|value": "to write",
|
||||||
"console.sendToScreen": "Sends the log messages to the brick screen and uses the brick up and down buttons to scroll.",
|
"console.sendToScreen": "Sends the log messages to the brick screen and uses the brick up and down buttons to scroll.",
|
||||||
"control": "Program controls and events.",
|
"control": "Program controls and events.",
|
||||||
|
"control.Timer": "A timer",
|
||||||
|
"control.Timer.millis": "Gets the elapsed time in millis since the last reset",
|
||||||
|
"control.Timer.pauseUntil": "Pauses until the timer reaches the given amount of milliseconds",
|
||||||
|
"control.Timer.pauseUntil|param|ms": "how long to pause for, eg: 5, 100, 200, 500, 1000, 2000",
|
||||||
|
"control.Timer.reset": "Resets the timer",
|
||||||
|
"control.Timer.seconds": "Gets the elapsed time in seconds since the last reset",
|
||||||
"control.allocateNotifyEvent": "Allocates the next user notification event",
|
"control.allocateNotifyEvent": "Allocates the next user notification event",
|
||||||
"control.deviceFirmwareVersion": "Determine the version of system software currently running.",
|
"control.deviceFirmwareVersion": "Determine the version of system software currently running.",
|
||||||
"control.dmesg": "Write data to DMESG debugging buffer.",
|
"control.dmesg": "Write data to DMESG debugging buffer.",
|
||||||
@ -61,6 +67,8 @@
|
|||||||
"control.raiseEvent|param|value": "Component specific code indicating the cause of the event.",
|
"control.raiseEvent|param|value": "Component specific code indicating the cause of the event.",
|
||||||
"motors.Motor.angle": "Gets motor angle.",
|
"motors.Motor.angle": "Gets motor angle.",
|
||||||
"motors.Motor.clearCounts": "Clears the motor count",
|
"motors.Motor.clearCounts": "Clears the motor count",
|
||||||
|
"motors.Motor.setRegulated": "Indicates if the motor speed should be regulated. Default is true.",
|
||||||
|
"motors.Motor.setRegulated|param|value": "true for regulated motor",
|
||||||
"motors.Motor.speed": "Gets motor actual speed.",
|
"motors.Motor.speed": "Gets motor actual speed.",
|
||||||
"motors.Motor.tacho": "Gets motor tachometer count.",
|
"motors.Motor.tacho": "Gets motor tachometer count.",
|
||||||
"motors.Motor.toString": "Returns the status of the motor",
|
"motors.Motor.toString": "Returns the status of the motor",
|
||||||
@ -71,7 +79,7 @@
|
|||||||
"motors.MotorBase.setBrake": "Sets the automatic brake on or off when the motor is off",
|
"motors.MotorBase.setBrake": "Sets the automatic brake on or off when the motor is off",
|
||||||
"motors.MotorBase.setBrake|param|brake": "a value indicating if the motor should break when off",
|
"motors.MotorBase.setBrake|param|brake": "a value indicating if the motor should break when off",
|
||||||
"motors.MotorBase.setReversed": "Reverses the motor polarity",
|
"motors.MotorBase.setReversed": "Reverses the motor polarity",
|
||||||
"motors.MotorBase.setSpeed": "Sets the motor speed for limited time or distance",
|
"motors.MotorBase.setSpeed": "Sets the motor speed for limited time or distance.",
|
||||||
"motors.MotorBase.setSpeed|param|speed": "the speed from ``100`` full forward to ``-100`` full backward, eg: 50",
|
"motors.MotorBase.setSpeed|param|speed": "the speed from ``100`` full forward to ``-100`` full backward, eg: 50",
|
||||||
"motors.MotorBase.setSpeed|param|unit": "(optional) unit of the value",
|
"motors.MotorBase.setSpeed|param|unit": "(optional) unit of the value",
|
||||||
"motors.MotorBase.setSpeed|param|value": "(optional) measured distance or rotation",
|
"motors.MotorBase.setSpeed|param|value": "(optional) measured distance or rotation",
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
|
"BrickLight.GreenFlash|block": "green flash",
|
||||||
|
"BrickLight.GreenPulse|block": "green pulse",
|
||||||
|
"BrickLight.Green|block": "green",
|
||||||
|
"BrickLight.Off|block": "off",
|
||||||
|
"BrickLight.OrangeFlash|block": "orange flash",
|
||||||
|
"BrickLight.OrangePulse|block": "orange pulse",
|
||||||
|
"BrickLight.Orange|block": "orange",
|
||||||
|
"BrickLight.RedFlash|block": "red flash",
|
||||||
|
"BrickLight.RedPulse|block": "red pulse",
|
||||||
|
"BrickLight.Red|block": "red",
|
||||||
"ButtonEvent.Click|block": "click",
|
"ButtonEvent.Click|block": "click",
|
||||||
"ButtonEvent.Down|block": "down",
|
"ButtonEvent.Down|block": "down",
|
||||||
"ButtonEvent.Up|block": "up",
|
"ButtonEvent.Up|block": "up",
|
||||||
"LightsPattern.GreenFlash|block": "Flashing Green",
|
|
||||||
"LightsPattern.GreenPulse|block": "Pulsing Green",
|
|
||||||
"LightsPattern.Green|block": "Green",
|
|
||||||
"LightsPattern.Off|block": "Off",
|
|
||||||
"LightsPattern.OrangeFlash|block": "Flashing Orange",
|
|
||||||
"LightsPattern.OrangePulse|block": "Pulsing Orange",
|
|
||||||
"LightsPattern.Orange|block": "Orange",
|
|
||||||
"LightsPattern.RedFlash|block": "Flashing Red",
|
|
||||||
"LightsPattern.RedPulse|block": "Pulsing Red",
|
|
||||||
"LightsPattern.Red|block": "Red",
|
|
||||||
"MoveUnit.Degrees|block": "degrees",
|
"MoveUnit.Degrees|block": "degrees",
|
||||||
"MoveUnit.MilliSeconds|block": "milliseconds",
|
"MoveUnit.MilliSeconds|block": "milliseconds",
|
||||||
"MoveUnit.Rotations|block": "rotations",
|
"MoveUnit.Rotations|block": "rotations",
|
||||||
@ -30,15 +30,14 @@
|
|||||||
"brick.Button.pauseUntil|block": "pause until %button|%event",
|
"brick.Button.pauseUntil|block": "pause until %button|%event",
|
||||||
"brick.Button.wasPressed|block": "%button|was pressed",
|
"brick.Button.wasPressed|block": "%button|was pressed",
|
||||||
"brick.batteryLevel|block": "battery level",
|
"brick.batteryLevel|block": "battery level",
|
||||||
"brick.buttonDown|block": "down",
|
"brick.buttonDown|block": "button down",
|
||||||
"brick.buttonEnter|block": "enter",
|
"brick.buttonEnter|block": "button enter",
|
||||||
"brick.buttonLeft|block": "left",
|
"brick.buttonLeft|block": "button left",
|
||||||
"brick.buttonRight|block": "right",
|
"brick.buttonRight|block": "button right",
|
||||||
"brick.buttonUp|block": "up",
|
"brick.buttonUp|block": "button up",
|
||||||
"brick.clearScreen|block": "clear screen",
|
"brick.clearScreen|block": "clear screen",
|
||||||
"brick.lightPattern|block": "%pattern",
|
|
||||||
"brick.printPorts|block": "print ports",
|
"brick.printPorts|block": "print ports",
|
||||||
"brick.setLight|block": "set light to %pattern=led_pattern",
|
"brick.setLight|block": "set light to %pattern",
|
||||||
"brick.showImage|block": "show image %image=screen_image_picker",
|
"brick.showImage|block": "show image %image=screen_image_picker",
|
||||||
"brick.showNumber|block": "show number %name|at line %line",
|
"brick.showNumber|block": "show number %name|at line %line",
|
||||||
"brick.showString|block": "show string %text|at line %line",
|
"brick.showString|block": "show string %text|at line %line",
|
||||||
@ -48,17 +47,32 @@
|
|||||||
"console.log|block": "console|log %text",
|
"console.log|block": "console|log %text",
|
||||||
"console.sendToScreen|block": "send console to screen",
|
"console.sendToScreen|block": "send console to screen",
|
||||||
"console|block": "console",
|
"console|block": "console",
|
||||||
|
"control.Timer.millis|block": "%timer|millis",
|
||||||
|
"control.Timer.pauseUntil|block": "%timer|pause until (ms) %ms",
|
||||||
|
"control.Timer.reset|block": "%timer|reset",
|
||||||
|
"control.Timer.seconds|block": "%timer|seconds",
|
||||||
"control.raiseEvent|block": "raise event|from %src|with value %value",
|
"control.raiseEvent|block": "raise event|from %src|with value %value",
|
||||||
|
"control.timer1|block": "timer 1",
|
||||||
|
"control.timer2|block": "timer 2",
|
||||||
|
"control.timer3|block": "timer 3",
|
||||||
|
"control.timer4|block": "timer 4",
|
||||||
|
"control.timer5|block": "timer 5",
|
||||||
|
"control.timer6|block": "timer 6",
|
||||||
|
"control.timer7|block": "timer 7",
|
||||||
|
"control.timer8|block": "timer 8",
|
||||||
"control|block": "control",
|
"control|block": "control",
|
||||||
"motors.Motor.angle|block": "%motor|angle",
|
"motors.Motor.angle|block": "%motor|angle",
|
||||||
"motors.Motor.clearCounts|block": "%motor|clear counts",
|
"motors.Motor.clearCounts|block": "%motor|clear counts",
|
||||||
|
"motors.Motor.setRegulated|block": "set %motor|regulated %value",
|
||||||
"motors.Motor.speed|block": "%motor|speed",
|
"motors.Motor.speed|block": "%motor|speed",
|
||||||
"motors.Motor.tacho|block": "%motor|tacho",
|
"motors.Motor.tacho|block": "%motor|tacho",
|
||||||
"motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready",
|
"motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready",
|
||||||
|
"motors.MotorBase.reset|block": "%motors|reset",
|
||||||
"motors.MotorBase.setBrake|block": "set %motor|brake %brake",
|
"motors.MotorBase.setBrake|block": "set %motor|brake %brake",
|
||||||
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed",
|
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed",
|
||||||
"motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%",
|
"motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%",
|
||||||
"motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio|speed %speed=motorSpeedPicker|%",
|
"motors.MotorBase.stop|block": "%motors|stop",
|
||||||
|
"motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio=motorTurnRatioPicker|speed %speed=motorSpeedPicker|%",
|
||||||
"motors.SynchedMotorPair.tank|block": "tank %motors|%speedLeft=motorSpeedPicker|%|%speedRight=motorSpeedPicker|%",
|
"motors.SynchedMotorPair.tank|block": "tank %motors|%speedLeft=motorSpeedPicker|%|%speedRight=motorSpeedPicker|%",
|
||||||
"motors.largeAB|block": "large A+B",
|
"motors.largeAB|block": "large A+B",
|
||||||
"motors.largeAD|block": "large A+D",
|
"motors.largeAD|block": "large A+D",
|
||||||
@ -90,7 +104,6 @@
|
|||||||
"{id:category}Serial": "Serial",
|
"{id:category}Serial": "Serial",
|
||||||
"{id:group}Buttons": "Buttons",
|
"{id:group}Buttons": "Buttons",
|
||||||
"{id:group}Counters": "Counters",
|
"{id:group}Counters": "Counters",
|
||||||
"{id:group}Light": "Light",
|
|
||||||
"{id:group}More": "More",
|
"{id:group}More": "More",
|
||||||
"{id:group}Move": "Move",
|
"{id:group}Move": "Move",
|
||||||
"{id:group}Screen": "Screen",
|
"{id:group}Screen": "Screen",
|
||||||
|
@ -2,36 +2,26 @@
|
|||||||
/**
|
/**
|
||||||
* Patterns for lights under the buttons.
|
* Patterns for lights under the buttons.
|
||||||
*/
|
*/
|
||||||
const enum LightsPattern {
|
const enum BrickLight {
|
||||||
//% block=Off enumval=0
|
//% block=off enumval=0
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
Off = 0,
|
Off = 0,
|
||||||
//% block=Green enumval=1
|
//% block=green enumval=1
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
Green = 1,
|
Green = 1,
|
||||||
//% block=Red enumval=2
|
//% block=red enumval=2
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
Red = 2,
|
Red = 2,
|
||||||
//% block=Orange enumval=3
|
//% block=orange enumval=3
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
Orange = 3,
|
Orange = 3,
|
||||||
//% block="Flashing Green" enumval=4
|
//% block="green flash" enumval=4
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
GreenFlash = 4,
|
GreenFlash = 4,
|
||||||
//% block="Flashing Red" enumval=5
|
//% block="red flash" enumval=5
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
RedFlash = 5,
|
RedFlash = 5,
|
||||||
//% block="Flashing Orange" enumval=6
|
//% block="orange flash" enumval=6
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
OrangeFlash = 6,
|
OrangeFlash = 6,
|
||||||
//% block="Pulsing Green" enumval=7
|
//% block="green pulse" enumval=7
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
GreenPulse = 7,
|
GreenPulse = 7,
|
||||||
//% block="Pulsing Red" enumval=8
|
//% block="red pulse" enumval=8
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
RedPulse = 8,
|
RedPulse = 8,
|
||||||
//% block="Pulsing Orange" enumval=9
|
//% block="orange pulse" enumval=9
|
||||||
//% blockIdentity=brick.lightPattern
|
|
||||||
OrangePulse = 9,
|
OrangePulse = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +160,7 @@ namespace brick {
|
|||||||
// this needs to be done in query(), which is run without the main JS execution mutex
|
// this needs to be done in query(), which is run without the main JS execution mutex
|
||||||
// otherwise, while(true){} will lock the device
|
// otherwise, while(true){} will lock the device
|
||||||
if (ret & DAL.BUTTON_ID_ESCAPE) {
|
if (ret & DAL.BUTTON_ID_ESCAPE) {
|
||||||
|
motors.stopAllMotors(); // ensuring that all motors are off
|
||||||
control.reset()
|
control.reset()
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
@ -203,31 +194,31 @@ namespace brick {
|
|||||||
/**
|
/**
|
||||||
* Enter button on the EV3 Brick.
|
* Enter button on the EV3 Brick.
|
||||||
*/
|
*/
|
||||||
//% whenUsed block="enter" weight=95 fixedInstance
|
//% whenUsed block="button enter" weight=95 fixedInstance
|
||||||
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
|
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Left button on the EV3 Brick.
|
* Left button on the EV3 Brick.
|
||||||
*/
|
*/
|
||||||
//% whenUsed block="left" weight=95 fixedInstance
|
//% whenUsed block="button left" weight=95 fixedInstance
|
||||||
export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT)
|
export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Right button on the EV3 Brick.
|
* Right button on the EV3 Brick.
|
||||||
*/
|
*/
|
||||||
//% whenUsed block="right" weight=94 fixedInstance
|
//% whenUsed block="button right" weight=94 fixedInstance
|
||||||
export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT)
|
export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Up button on the EV3 Brick.
|
* Up button on the EV3 Brick.
|
||||||
*/
|
*/
|
||||||
//% whenUsed block="up" weight=95 fixedInstance
|
//% whenUsed block="button up" weight=95 fixedInstance
|
||||||
export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP)
|
export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Down button on the EV3 Brick.
|
* Down button on the EV3 Brick.
|
||||||
*/
|
*/
|
||||||
//% whenUsed block="down" weight=95 fixedInstance
|
//% whenUsed block="button down" weight=95 fixedInstance
|
||||||
export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN)
|
export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,32 +242,21 @@ namespace control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace brick {
|
namespace brick {
|
||||||
let currPattern: LightsPattern
|
// the brick starts with the red color
|
||||||
|
let currPattern: BrickLight = BrickLight.Red;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set lights.
|
* Set lights.
|
||||||
* @param pattern the lights pattern to use.
|
* @param pattern the lights pattern to use. eg: BrickLight.Orange
|
||||||
*/
|
*/
|
||||||
//% blockId=setLights block="set light to %pattern=led_pattern"
|
//% blockId=setLights block="set light to %pattern"
|
||||||
//% weight=100 group="Buttons"
|
//% weight=100 group="Buttons"
|
||||||
export function setLight(pattern: number): void {
|
export function setLight(pattern: BrickLight): void {
|
||||||
if (currPattern === pattern)
|
if (currPattern === pattern)
|
||||||
return
|
return
|
||||||
currPattern = pattern
|
currPattern = pattern;
|
||||||
let cmd = output.createBuffer(2)
|
const cmd = output.createBuffer(2)
|
||||||
cmd[0] = pattern + 48
|
cmd[0] = pattern + 48
|
||||||
brick.internal.getBtnsMM().write(cmd)
|
brick.internal.getBtnsMM().write(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pattern block.
|
|
||||||
* @param pattern the lights pattern to use. eg: LightsPattern.Green
|
|
||||||
*/
|
|
||||||
//% blockId=led_pattern block="%pattern"
|
|
||||||
//% shim=TD_ID colorSecondary="#6e9a36" group="Light"
|
|
||||||
//% blockHidden=true useEnumVal=1 pattern.fieldOptions.decompileLiterals=1
|
|
||||||
export function lightPattern(pattern: LightsPattern): number {
|
|
||||||
return pattern;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace console {
|
|||||||
|
|
||||||
namespace console.screen {
|
namespace console.screen {
|
||||||
const maxLines = 100;
|
const maxLines = 100;
|
||||||
const screenLines = 8;
|
const screenLines = 10;
|
||||||
let lines: string[];
|
let lines: string[];
|
||||||
let scrollPosition = 0;
|
let scrollPosition = 0;
|
||||||
|
|
||||||
@ -66,8 +66,8 @@ namespace console.screen {
|
|||||||
if (!lines) {
|
if (!lines) {
|
||||||
lines = [];
|
lines = [];
|
||||||
console.addListener(log);
|
console.addListener(log);
|
||||||
brick.buttonUp.onEvent(ButtonEvent.Click, () => scroll(-1))
|
brick.buttonUp.onEvent(ButtonEvent.Click, () => scroll(-3))
|
||||||
brick.buttonDown.onEvent(ButtonEvent.Click, () => scroll(1))
|
brick.buttonDown.onEvent(ButtonEvent.Click, () => scroll(3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
libs/core/enums.d.ts
vendored
11
libs/core/enums.d.ts
vendored
@ -1,6 +1,17 @@
|
|||||||
// Auto-generated. Do not edit.
|
// Auto-generated. Do not edit.
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mode for lseek()
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare const enum SeekWhence {
|
||||||
|
Set = 0,
|
||||||
|
Current = 1,
|
||||||
|
End = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drawing modes
|
* Drawing modes
|
||||||
*/
|
*/
|
||||||
|
@ -114,23 +114,7 @@
|
|||||||
"progressWaterLevel3": "iVBORw0KGgoAAAANSUhEUgAAALIAAACAAQAAAACHQw5jAAABP0lEQVR42u2VMWrEMBBFRxGsGrNqXYT4CltuFV9lj5EqVlhImyPkKoKFbJcrrHKCKJ2XKFb+BGxsGBdbBRJ/mGHm+VtjJGNT/srQO6cG8cnFKXvKLVdHRFcjfXD3xDyybY9IFVJgbpgHtilEa5E8XJ1m/gJbVwJFXuwRrqSYa9hSCZt/A1/B1VLjqdMG1mu0bgeD4W5Te2r1A6YVJne0qfNP57fWU9AY5dYKd29tDgodldoTqagjGaoc3VAiiibQmlg1ApeIQIjuufDUq+C0Q1z1xaJFi/60iluZ28aJ3Jy9yPU5iFxlmesZvsry+kUz8/z/5qTuZKyizM2F3IYZfnDyuR7kc61fL+P4qYmq0mCZ+tuhfHZjPvhV8iKnMVejuZNXrjnK3O77aeo03hEzNGqyUcbNnJdfPjqLFv2+vgH+JtBJ4nz/SAAAAABJRU5ErkJggg==",
|
"progressWaterLevel3": "iVBORw0KGgoAAAANSUhEUgAAALIAAACAAQAAAACHQw5jAAABP0lEQVR42u2VMWrEMBBFRxGsGrNqXYT4CltuFV9lj5EqVlhImyPkKoKFbJcrrHKCKJ2XKFb+BGxsGBdbBRJ/mGHm+VtjJGNT/srQO6cG8cnFKXvKLVdHRFcjfXD3xDyybY9IFVJgbpgHtilEa5E8XJ1m/gJbVwJFXuwRrqSYa9hSCZt/A1/B1VLjqdMG1mu0bgeD4W5Te2r1A6YVJne0qfNP57fWU9AY5dYKd29tDgodldoTqagjGaoc3VAiiibQmlg1ApeIQIjuufDUq+C0Q1z1xaJFi/60iluZ28aJ3Jy9yPU5iFxlmesZvsry+kUz8/z/5qTuZKyizM2F3IYZfnDyuR7kc61fL+P4qYmq0mCZ+tuhfHZjPvhV8iKnMVejuZNXrjnK3O77aeo03hEzNGqyUcbNnJdfPjqLFv2+vgH+JtBJ4nz/SAAAAABJRU5ErkJggg==",
|
||||||
"systemAccept1": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAAQElEQVR42mM4wMDMsP//X4b6//+AWI6h/p8dQ/2fOob6H/8YKj/+Y6h4/I+hxvkfQx07UJ4fiOf/A6sF6QHqBQDsYh9jNdETHwAAAABJRU5ErkJggg==",
|
"systemAccept1": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAAQElEQVR42mM4wMDMsP//X4b6//+AWI6h/p8dQ/2fOob6H/8YKj/+Y6h4/I+hxvkfQx07UJ4fiOf/A6sF6QHqBQDsYh9jNdETHwAAAABJRU5ErkJggg==",
|
||||||
"systemAccept2": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAAQUlEQVR42mM4wMDMsP//X4YEBjYGB4ZHDA6MhxgcmJsYHNiZGNz4mBjcZZgYnPcwMTj+YGJw+ADECUxgtSA9QL0A+IIPxwiZFtwAAAAASUVORK5CYII=",
|
"systemAccept2": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAAQUlEQVR42mM4wMDMsP//X4YEBjYGB4ZHDA6MhxgcmJsYHNiZGNz4mBjcZZgYnPcwMTj+YGJw+ADECUxgtSA9QL0A+IIPxwiZFtwAAAAASUVORK5CYII=",
|
||||||
"systemAlert": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAVAQAAAAB0khOLAAAARUlEQVR42iXD0QmAIAAE0IvWCtqmMbLG8MtVhAZwjBvALyE85XzwoE/QO8f5WPsd0K+An6c3Jq8sThIUUVg9qfmDDRn7AD/WMAQEJ+pCAAAAAElFTkSuQmCC",
|
|
||||||
"systemBox": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAAGklEQVR42mM4wMDMsP//X4b6//9IwiA9QL0AlQYkzY8nCoAAAAAASUVORK5CYII=",
|
"systemBox": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAAGklEQVR42mM4wMDMsP//X4b6//9IwiA9QL0AlQYkzY8nCoAAAAAASUVORK5CYII=",
|
||||||
"systemBusy0": "iVBORw0KGgoAAAANSUhEUgAAABMAAAAPAQAAAAAuP8mBAAAAMElEQVR42mPY/38Bg/x/BgbnHw4Msd8dGKLeA+k4IL0XSGdB6TioOFAepA6kHqgPAJCPFdTsOCPGAAAAAElFTkSuQmCC",
|
|
||||||
"systemBusy1": "iVBORw0KGgoAAAANSUhEUgAAAA8AAAATAQAAAABnuWoHAAAAOUlEQVR42mNoYGKw/8EAJO9/A6GrYQyv1jF8jWP4tY/hbx3D730M3+4xvH/HcO8bw90yhlvbGGDqAdjhGYsKgwC5AAAAAElFTkSuQmCC",
|
|
||||||
"systemDecline1": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAANUlEQVR42mM4wMDMsP//X4b6//8Y6urtGOrt6hjq5/xjqD8JxI+hGMQGiQHlwGqAakF6gHoBybUeX0RcSJEAAAAASUVORK5CYII=",
|
"systemDecline1": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAANUlEQVR42mM4wMDMsP//X4b6//8Y6urtGOrt6hjq5/xjqD8JxI+hGMQGiQHlwGqAakF6gHoBybUeX0RcSJEAAAAASUVORK5CYII=",
|
||||||
"systemDecline2": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAANUlEQVR42mM4wMDMsP//X4YEBjYGx4ZDDA4HmxgckpkYHMyAWAaKQWyQGFAOpAakFqQHqBcAGz4QyzSHE/gAAAAASUVORK5CYII=",
|
"systemDecline2": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAQAQAAAAAkX4I4AAAANUlEQVR42mM4wMDMsP//X4YEBjYGx4ZDDA4HmxgckpkYHMyAWAaKQWyQGFAOpAakFqQHqBcAGz4QyzSHE/gAAAAASUVORK5CYII="
|
||||||
"systemDotEmpty": "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAfAQAAAAA31SuUAAAAYklEQVR42oWOMQ5AQBRE5yZ7FEfSKTmC25CQuILehkahkc12IvgjRqHUTPX/ew+MzsByNlhxGq7ochz90mFL9gmBFjCSGTxZoSUb1OTwTkquP/Md61cU8USWQzZ5VaCWp+oGeLZn9EklJaAAAAAASUVORK5CYII=",
|
|
||||||
"systemDotFull": "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAfAQAAAAA31SuUAAAAX0lEQVR42mP4/0H+H8P//sf/GP7V//nH8PeDfB3D7wPs+xi+MzDeY3jHAER3GBjKGG4wMJgx7GBgsGLYwMAgBSESGBh4CBAIxWC9YFPA5oFNBtsBtg1sL9gFYLeAXAUAPIwyHWLMTS8AAAAASUVORK5CYII=",
|
|
||||||
"systemEv3small": "iVBORw0KGgoAAAANSUhEUgAAACsAAAANAQAAAAAY06pGAAAAPUlEQVR42mNg4LFvYwACFEr+n32fPYiS5/8P5PLLyz8AUXwQqs8eSMn/b7H/D6IO1NmDBA/UgbTzP/gHpwBcwBWO2QYBDwAAAABJRU5ErkJggg==",
|
|
||||||
"systemPlay": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQAAAAA3iMLMAAAAMElEQVR42mP4Y8/wsZ/h+XOG858Z5v5k2POXwcaGoUYOhIAMIBcoCJQCKgAq+2MPAAFKFVmziLfGAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider0": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAEklEQVR42mM4YMBwfwPV0AEDAHmKKNims3dJAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider1": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAGklEQVR42mM4YMBwfwNFCAKuGjCc2sBwwAAAT7olG9TpXdAAAAAASUVORK5CYII=",
|
|
||||||
"systemSlider2": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAG0lEQVR42mM4YMBwfwM5CAJObWC4aoAgDxgAACpUJGftPg+WAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider3": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAG0lEQVR42mM4YMBwfwMJCAKuGjCc2oCFPGAAAPSIIz417p4OAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider4": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAG0lEQVR42mM4YMBwfwNhBAGnNjBcNcBHHjAAAMJ6IooqNLP/AAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider5": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAG0lEQVR42mM4YMBwfwNOBAFXDRhObSCKPGAAAHfbIWHuFKlNAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider6": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAG0lEQVR42mM4YMBwfwM6goBTGxiuGpBGHjAAADklIK1PooVQAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider7": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAG0lEQVR42mM4YMBwfwMUQcBVA4ZTG8gkDxgAANmVH4SOiUHMAAAAAElFTkSuQmCC",
|
|
||||||
"systemSlider8": "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAbAQAAAABg3VNpAAAAFElEQVR42mM4YMBwagPDVSqRBwwASoohT92wVBIAAAAASUVORK5CYII="
|
|
||||||
}
|
}
|
@ -220,41 +220,10 @@ namespace images {
|
|||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
||||||
export const systemAccept2 = screen.unpackPNG(hex``);
|
export const systemAccept2 = screen.unpackPNG(hex``);
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
||||||
export const systemAlert = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemBox = screen.unpackPNG(hex``);
|
export const systemBox = screen.unpackPNG(hex``);
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
||||||
export const systemBusy0 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemBusy1 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemDecline1 = screen.unpackPNG(hex``);
|
export const systemDecline1 = screen.unpackPNG(hex``);
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
||||||
export const systemDecline2 = screen.unpackPNG(hex``);
|
export const systemDecline2 = screen.unpackPNG(hex``);
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
||||||
export const systemDotEmpty = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemDotFull = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemEv3small = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemPlay = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider0 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider1 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider2 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider3 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider4 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider5 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider6 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider7 = screen.unpackPNG(hex``);
|
|
||||||
//% fixedInstance jres blockIdentity=brick.__imagePicker
|
|
||||||
export const systemSlider8 = screen.unpackPNG(hex``);
|
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ namespace sensors.internal {
|
|||||||
init();
|
init();
|
||||||
return {
|
return {
|
||||||
temp: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryTemp),
|
temp: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryTemp),
|
||||||
current: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent)
|
current: Math.round(analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent) / 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,8 +310,9 @@ namespace sensors.internal {
|
|||||||
return getUartNumber(fmt, off, this._port)
|
return getUartNumber(fmt, off, this._port)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected reset() {
|
reset() {
|
||||||
if (this.isActive()) uartReset(this._port);
|
if (this.isActive()) uartReset(this._port);
|
||||||
|
this.realmode = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,16 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mode for lseek()
|
||||||
|
*/
|
||||||
|
enum class SeekWhence {
|
||||||
|
Set = 0,
|
||||||
|
Current = 1,
|
||||||
|
End = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace pxt {
|
namespace pxt {
|
||||||
PXT_VTABLE_CTOR(MMap) {
|
PXT_VTABLE_CTOR(MMap) {
|
||||||
length = 0;
|
length = 0;
|
||||||
@ -111,4 +121,10 @@ int read(MMap *mmap, Buffer data) {
|
|||||||
return ::read(mmap->fd, data->data, data->length);
|
return ::read(mmap->fd, data->data, data->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set pointer on the underlaying file. */
|
||||||
|
//%
|
||||||
|
int lseek(MMap *mmap, int offset, SeekWhence whence) {
|
||||||
|
return ::lseek(mmap->fd, offset, (int)whence);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -11,4 +11,15 @@ namespace motors {
|
|||||||
export function __speedPicker(speed: number): number {
|
export function __speedPicker(speed: number): number {
|
||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A turn ratio picker
|
||||||
|
* @param turnratio the turn ratio, eg: 0
|
||||||
|
*/
|
||||||
|
//% blockId=motorTurnRatioPicker block="%turnratio" shim=TD_ID
|
||||||
|
//% turnratio.fieldEditor="turnratio" colorSecondary="#FFFFFF"
|
||||||
|
//% weight=0 blockHidden=1 turnRatio.fieldOptions.decompileLiterals=1
|
||||||
|
export function __turnRatioPicker(turnratio: number): number {
|
||||||
|
return turnratio;
|
||||||
|
}
|
||||||
}
|
}
|
@ -111,7 +111,7 @@ namespace motors {
|
|||||||
* Stops all motors
|
* Stops all motors
|
||||||
*/
|
*/
|
||||||
//% blockId=motorStopAll block="stop all motors"
|
//% blockId=motorStopAll block="stop all motors"
|
||||||
//% weight=5
|
//% weight=1
|
||||||
//% group="Move"
|
//% group="Move"
|
||||||
export function stopAllMotors() {
|
export function stopAllMotors() {
|
||||||
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
|
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
|
||||||
@ -175,7 +175,7 @@ namespace motors {
|
|||||||
*/
|
*/
|
||||||
//% blockId=motorSetReversed block="set %motor|reversed %reversed"
|
//% blockId=motorSetReversed block="set %motor|reversed %reversed"
|
||||||
//% reversed.fieldEditor=toggleonoff
|
//% reversed.fieldEditor=toggleonoff
|
||||||
//% weight=59
|
//% weight=59 blockGap=8
|
||||||
//% group="Move"
|
//% group="Move"
|
||||||
setReversed(reversed: boolean) {
|
setReversed(reversed: boolean) {
|
||||||
this.init();
|
this.init();
|
||||||
@ -187,7 +187,9 @@ namespace motors {
|
|||||||
/**
|
/**
|
||||||
* Stops the motor(s).
|
* Stops the motor(s).
|
||||||
*/
|
*/
|
||||||
//%
|
//% weight=6 blockGap=8
|
||||||
|
//% group="Move"
|
||||||
|
//% blockId=motorStop block="%motors|stop"
|
||||||
stop() {
|
stop() {
|
||||||
this.init();
|
this.init();
|
||||||
stop(this._port, this._brake);
|
stop(this._port, this._brake);
|
||||||
@ -196,14 +198,16 @@ namespace motors {
|
|||||||
/**
|
/**
|
||||||
* Resets the motor(s).
|
* Resets the motor(s).
|
||||||
*/
|
*/
|
||||||
//%
|
//% weight=5
|
||||||
|
//% group="Move"
|
||||||
|
//% blockId=motorReset block="%motors|reset"
|
||||||
reset() {
|
reset() {
|
||||||
this.init();
|
this.init();
|
||||||
reset(this._port);
|
reset(this._port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the motor speed for limited time or distance
|
* Sets the motor speed for limited time or distance.
|
||||||
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
|
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
|
||||||
* @param value (optional) measured distance or rotation
|
* @param value (optional) measured distance or rotation
|
||||||
* @param unit (optional) unit of the value
|
* @param unit (optional) unit of the value
|
||||||
@ -214,10 +218,17 @@ namespace motors {
|
|||||||
setSpeed(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
setSpeed(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
||||||
this.init();
|
this.init();
|
||||||
speed = Math.clamp(-100, 100, speed >> 0);
|
speed = Math.clamp(-100, 100, speed >> 0);
|
||||||
|
// stop if speed is 0
|
||||||
if (!speed) {
|
if (!speed) {
|
||||||
this.stop();
|
this.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// special: 0 is infinity
|
||||||
|
if (value == 0) {
|
||||||
|
this._setSpeed(speed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// timed motor moves
|
||||||
let useSteps: boolean;
|
let useSteps: boolean;
|
||||||
let stepsOrTime: number;
|
let stepsOrTime: number;
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
@ -240,6 +251,8 @@ namespace motors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._move(useSteps, stepsOrTime, speed);
|
this._move(useSteps, stepsOrTime, speed);
|
||||||
|
// wait till motor is done with this work
|
||||||
|
this.pauseUntilReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,10 +282,12 @@ namespace motors {
|
|||||||
//% fixedInstances
|
//% fixedInstances
|
||||||
export class Motor extends MotorBase {
|
export class Motor extends MotorBase {
|
||||||
private _large: boolean;
|
private _large: boolean;
|
||||||
|
private _regulated: boolean;
|
||||||
|
|
||||||
constructor(port: Output, large: boolean) {
|
constructor(port: Output, large: boolean) {
|
||||||
super(port, () => this.__init(), (speed) => this.__setSpeed(speed), (steps, stepsOrTime, speed) => this.__move(steps, stepsOrTime, speed));
|
super(port, () => this.__init(), (speed) => this.__setSpeed(speed), (steps, stepsOrTime, speed) => this.__move(steps, stepsOrTime, speed));
|
||||||
this._large = large;
|
this._large = large;
|
||||||
|
this._regulated = true;
|
||||||
this.markUsed();
|
this.markUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +303,7 @@ namespace motors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private __setSpeed(speed: number) {
|
private __setSpeed(speed: number) {
|
||||||
const b = mkCmd(this._port, DAL.opOutputSpeed, 1)
|
const b = mkCmd(this._port, this._regulated ? DAL.opOutputSpeed : DAL.opOutputPower, 1)
|
||||||
b.setNumber(NumberFormat.Int8LE, 2, speed)
|
b.setNumber(NumberFormat.Int8LE, 2, speed)
|
||||||
writePWM(b)
|
writePWM(b)
|
||||||
if (speed) {
|
if (speed) {
|
||||||
@ -302,11 +317,24 @@ namespace motors {
|
|||||||
step1: 0,
|
step1: 0,
|
||||||
step2: stepsOrTime,
|
step2: stepsOrTime,
|
||||||
step3: 0,
|
step3: 0,
|
||||||
speed: speed,
|
speed: this._regulated ? speed : undefined,
|
||||||
|
power: this._regulated ? undefined : speed,
|
||||||
useBrake: this._brake
|
useBrake: this._brake
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the motor speed should be regulated. Default is true.
|
||||||
|
* @param value true for regulated motor
|
||||||
|
*/
|
||||||
|
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value"
|
||||||
|
//% value.fieldEditor=toggleonoff
|
||||||
|
//% weight=58
|
||||||
|
//% group="Move"
|
||||||
|
setRegulated(value: boolean) {
|
||||||
|
this._regulated = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets motor actual speed.
|
* Gets motor actual speed.
|
||||||
* @param motor the port which connects to the motor
|
* @param motor the port which connects to the motor
|
||||||
@ -474,7 +502,7 @@ namespace motors {
|
|||||||
* @param value (optional) move duration or rotation
|
* @param value (optional) move duration or rotation
|
||||||
* @param unit (optional) unit of the value
|
* @param unit (optional) unit of the value
|
||||||
*/
|
*/
|
||||||
//% blockId=motorPairSteer block="steer %chassis|turn ratio %turnRatio|speed %speed=motorSpeedPicker|%"
|
//% blockId=motorPairSteer block="steer %chassis|turn ratio %turnRatio=motorTurnRatioPicker|speed %speed=motorSpeedPicker|%"
|
||||||
//% weight=95
|
//% weight=95
|
||||||
//% turnRatio.min=-200 turnRatio=200
|
//% turnRatio.min=-200 turnRatio=200
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"mmap.cpp",
|
"mmap.cpp",
|
||||||
"control.cpp",
|
"control.cpp",
|
||||||
"console.ts",
|
"console.ts",
|
||||||
|
"timer.ts",
|
||||||
"serialnumber.cpp",
|
"serialnumber.cpp",
|
||||||
"buttons.ts",
|
"buttons.ts",
|
||||||
"png.cpp",
|
"png.cpp",
|
||||||
|
4
libs/core/shims.d.ts
vendored
4
libs/core/shims.d.ts
vendored
@ -41,6 +41,10 @@ declare interface MMap {
|
|||||||
/** Perform read(2) on the underlaying file */
|
/** Perform read(2) on the underlaying file */
|
||||||
//% shim=MMapMethods::read
|
//% shim=MMapMethods::read
|
||||||
read(data: Buffer): int32;
|
read(data: Buffer): int32;
|
||||||
|
|
||||||
|
/** Set pointer on the underlaying file. */
|
||||||
|
//% shim=MMapMethods::lseek
|
||||||
|
lseek(offset: int32, whence: SeekWhence): int32;
|
||||||
}
|
}
|
||||||
declare namespace control {
|
declare namespace control {
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ screen.clear()
|
|||||||
brick.print("PXT!", 10, 30, Draw.Quad)
|
brick.print("PXT!", 10, 30, Draw.Quad)
|
||||||
|
|
||||||
brick.drawRect(40, 40, 20, 10, Draw.Fill)
|
brick.drawRect(40, 40, 20, 10, Draw.Fill)
|
||||||
brick.setLight(LightsPattern.Orange)
|
brick.setLight(BrickLight.Orange)
|
||||||
|
|
||||||
brick.heart.doubled().draw(100, 50, Draw.Double | Draw.Transparent)
|
brick.heart.doubled().draw(100, 50, Draw.Double | Draw.Transparent)
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
|
|||||||
|
|
||||||
brick.buttonLeft.onEvent(ButtonEvent.Click, () => {
|
brick.buttonLeft.onEvent(ButtonEvent.Click, () => {
|
||||||
brick.drawRect(10, 70, 20, 10, Draw.Fill)
|
brick.drawRect(10, 70, 20, 10, Draw.Fill)
|
||||||
brick.setLight(LightsPattern.Red)
|
brick.setLight(BrickLight.Red)
|
||||||
brick.setFont(brick.microbitFont())
|
brick.setFont(brick.microbitFont())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
64
libs/core/timer.ts
Normal file
64
libs/core/timer.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
namespace control {
|
||||||
|
/**
|
||||||
|
* A timer
|
||||||
|
*/
|
||||||
|
//% fixedInstances
|
||||||
|
export class Timer {
|
||||||
|
start: number;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.start = control.millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the elapsed time in millis since the last reset
|
||||||
|
*/
|
||||||
|
//% blockId=timerMillis block="%timer|millis"
|
||||||
|
millis(): number {
|
||||||
|
return control.millis() - this.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the elapsed time in seconds since the last reset
|
||||||
|
*/
|
||||||
|
//% blockId=timerSeconds block="%timer|seconds"
|
||||||
|
seconds(): number {
|
||||||
|
return this.millis() / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the timer
|
||||||
|
*/
|
||||||
|
//% blockId=timerRest block="%timer|reset"
|
||||||
|
reset() {
|
||||||
|
this.start = control.millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses until the timer reaches the given amount of milliseconds
|
||||||
|
* @param ms how long to pause for, eg: 5, 100, 200, 500, 1000, 2000
|
||||||
|
*/
|
||||||
|
//% blockId=timerPauseUntil block="%timer|pause until (ms) %ms"
|
||||||
|
pauseUntil(ms: number) {
|
||||||
|
const remaining = this.millis() - ms;
|
||||||
|
loops.pause(Math.max(0, remaining));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//% whenUsed fixedInstance block="timer 1"
|
||||||
|
export const timer1 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 2"
|
||||||
|
export const timer2 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 3"
|
||||||
|
export const timer3 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 4"
|
||||||
|
export const timer4 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 5"
|
||||||
|
export const timer5 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 6"
|
||||||
|
export const timer6 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 7"
|
||||||
|
export const timer7 = new Timer();
|
||||||
|
//% whenUsed fixedInstance block="timer 8"
|
||||||
|
export const timer8 = new Timer();
|
||||||
|
}
|
3
libs/datalog/README.md
Normal file
3
libs/datalog/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Datalog
|
||||||
|
|
||||||
|
A tiny libraty to create CSV datalog files.
|
11
libs/datalog/_locales/datalog-jsdoc-strings.json
Normal file
11
libs/datalog/_locales/datalog-jsdoc-strings.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"datalog.addRow": "Starts a row of data",
|
||||||
|
"datalog.addValue": "Adds a cell to the row of data",
|
||||||
|
"datalog.addValue|param|name": "name of the cell, eg: \"x\"",
|
||||||
|
"datalog.addValue|param|value": "value of the cell, eg: 0",
|
||||||
|
"datalog.flush": "Commits any buffered row to disk",
|
||||||
|
"datalog.setEnabled": "Turns on or off datalogging",
|
||||||
|
"datalog.setFile": "Starts a new data logger for the given file",
|
||||||
|
"datalog.setFile|param|filename": "the filename, eg: \"datalog.csv\"",
|
||||||
|
"datalog.setStorage": "* @param storage custom storage solution"
|
||||||
|
}
|
7
libs/datalog/_locales/datalog-strings.json
Normal file
7
libs/datalog/_locales/datalog-strings.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"datalog.addRow|block": "datalog add row",
|
||||||
|
"datalog.addValue|block": "datalog add %name|=%value",
|
||||||
|
"datalog.setEnabled|block": "datalog %enabled",
|
||||||
|
"datalog|block": "datalog",
|
||||||
|
"{id:category}Datalog": "Datalog"
|
||||||
|
}
|
122
libs/datalog/datalog.ts
Normal file
122
libs/datalog/datalog.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
//% weight=100 color=#0fbc11 icon=""
|
||||||
|
namespace datalog {
|
||||||
|
let _headers: string[] = undefined;
|
||||||
|
let _headersLength: number;
|
||||||
|
let _values: number[];
|
||||||
|
let _buffer: string = "";
|
||||||
|
let _start: number;
|
||||||
|
let _filename = "datalog.csv";
|
||||||
|
let _storage: storage.Storage = storage.temporary;
|
||||||
|
let _enabled = true;
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
_headers = undefined;
|
||||||
|
_values = undefined;
|
||||||
|
_buffer = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (!_headers) {
|
||||||
|
_headers = [];
|
||||||
|
_headersLength = 0;
|
||||||
|
_start = control.millis();
|
||||||
|
_storage.remove(_filename);
|
||||||
|
}
|
||||||
|
_values = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function commit() {
|
||||||
|
// write row if any data
|
||||||
|
if (_values && _values.length > 0) {
|
||||||
|
// write headers for the first row
|
||||||
|
if (!_headersLength) {
|
||||||
|
_storage.appendCSVHeaders(_filename, _headers);
|
||||||
|
_headersLength = _storage.size(_filename);
|
||||||
|
}
|
||||||
|
// commit row data
|
||||||
|
_buffer += storage.toCSV(_values, _storage.csvSeparator);
|
||||||
|
// buffered writes
|
||||||
|
if (_buffer.length > 1024)
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear values
|
||||||
|
_values = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a row of data
|
||||||
|
*/
|
||||||
|
//% weight=100
|
||||||
|
//% blockId=datalogAddRow block="datalog add row"
|
||||||
|
export function addRow(): void {
|
||||||
|
if (!_enabled) return;
|
||||||
|
|
||||||
|
commit();
|
||||||
|
init();
|
||||||
|
const s = (control.millis() - _start) / 1000;
|
||||||
|
addValue("time (s)", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a cell to the row of data
|
||||||
|
* @param name name of the cell, eg: "x"
|
||||||
|
* @param value value of the cell, eg: 0
|
||||||
|
*/
|
||||||
|
//% weight=99
|
||||||
|
//% blockId=datalogAddValue block="datalog add %name|=%value"
|
||||||
|
export function addValue(name: string, value: number) {
|
||||||
|
if (!_values) return;
|
||||||
|
let i = _headers.indexOf(name);
|
||||||
|
if (i < 0) {
|
||||||
|
_headers.push(name);
|
||||||
|
i = _headers.length - 1;
|
||||||
|
}
|
||||||
|
_values[i] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new data logger for the given file
|
||||||
|
* @param filename the filename, eg: "datalog.csv"
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
export function setFile(filename: string) {
|
||||||
|
flush();
|
||||||
|
_filename = filename;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param storage custom storage solution
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
export function setStorage(storage: storage.Storage) {
|
||||||
|
flush();
|
||||||
|
_storage = storage;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits any buffered row to disk
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
export function flush() {
|
||||||
|
if (_buffer) {
|
||||||
|
const b = _buffer;
|
||||||
|
_buffer = "";
|
||||||
|
_storage.append(_filename, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on or off datalogging
|
||||||
|
* @param enabled
|
||||||
|
*/
|
||||||
|
//% blockId=datalogEnabled block="datalog %enabled"
|
||||||
|
//% enabled.fieldEditor=fieldonoff
|
||||||
|
export function setEnabled(enabled: boolean) {
|
||||||
|
flush();
|
||||||
|
_enabled = enabled;
|
||||||
|
}
|
||||||
|
}
|
16
libs/datalog/pxt.json
Normal file
16
libs/datalog/pxt.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "datalog",
|
||||||
|
"description": "Tiny data logging framework",
|
||||||
|
"files": [
|
||||||
|
"README.md",
|
||||||
|
"datalog.ts"
|
||||||
|
],
|
||||||
|
"testFiles": [
|
||||||
|
"test.ts"
|
||||||
|
],
|
||||||
|
"public": true,
|
||||||
|
"dependencies": {
|
||||||
|
"core": "file:../core",
|
||||||
|
"storage": "file:../storage"
|
||||||
|
}
|
||||||
|
}
|
6
libs/datalog/test.ts
Normal file
6
libs/datalog/test.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
loops.forever(function () {
|
||||||
|
datalog.addRow()
|
||||||
|
datalog.addValue("x", Math.random())
|
||||||
|
datalog.addValue("y", Math.random())
|
||||||
|
})
|
@ -8,7 +8,7 @@ namespace brick {
|
|||||||
|
|
||||||
//% color="#C8509B" weight=95 icon="\uf10f"
|
//% color="#C8509B" weight=95 icon="\uf10f"
|
||||||
//% labelLineWidth=0
|
//% labelLineWidth=0
|
||||||
//% groups='["Ultrasonic Sensor", "Touch Sensor", "Color Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Gyro Sensor"]'
|
//% groups='["Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Gyro Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Threshold"]'
|
||||||
//% groupIcons='["\uf101","\uf103","\uf102","","","\uf104"]'
|
//% groupIcons='["\uf101","\uf103","\uf102","","","\uf104"]'
|
||||||
namespace sensors {
|
namespace sensors {
|
||||||
}
|
}
|
||||||
@ -56,4 +56,9 @@ namespace loops {
|
|||||||
//% color="#1E5AA8"
|
//% color="#1E5AA8"
|
||||||
namespace light {
|
namespace light {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//% color="#b0b0b0" advanced=true weight=5
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
}
|
}
|
@ -10,6 +10,7 @@
|
|||||||
"base": "file:../base",
|
"base": "file:../base",
|
||||||
"core": "file:../core",
|
"core": "file:../core",
|
||||||
"music": "file:../music",
|
"music": "file:../music",
|
||||||
|
"mood": "file:../mood",
|
||||||
"color-sensor": "file:../color-sensor",
|
"color-sensor": "file:../color-sensor",
|
||||||
"touch-sensor": "file:../touch-sensor",
|
"touch-sensor": "file:../touch-sensor",
|
||||||
"ultrasonic-sensor": "file:../ultrasonic-sensor",
|
"ultrasonic-sensor": "file:../ultrasonic-sensor",
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"sensors.GyroSensor.angle": "Get the current angle from the gyroscope.",
|
"sensors.GyroSensor.angle": "Get the current angle from the gyroscope.",
|
||||||
"sensors.GyroSensor.calibrate": "Forces a calibration of the gyro. Must be called when the sensor is completely still.",
|
"sensors.GyroSensor.drift": "Gets the computed rate drift",
|
||||||
"sensors.GyroSensor.rotationRate": "Get the current rotation rate from the gyroscope."
|
"sensors.GyroSensor.rate": "Get the current rotation rate from the gyroscope.",
|
||||||
|
"sensors.GyroSensor.reset": "Forces a calibration of the gyro. Must be called when the sensor is completely still.",
|
||||||
|
"sensors.GyroSensor.setDriftCorrection": "Enables or disable drift correction"
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"sensors.GyroSensor.angle|block": "%sensor|angle",
|
"sensors.GyroSensor.angle|block": "%sensor|angle",
|
||||||
"sensors.GyroSensor.calibrate|block": "%sensor|calibrate",
|
"sensors.GyroSensor.rate|block": "%sensor|rate",
|
||||||
"sensors.GyroSensor.rotationRate|block": "%sensor|rotation rate",
|
"sensors.GyroSensor.reset|block": "%sensor|reset",
|
||||||
"sensors.gyro1|block": "gyro 1",
|
"sensors.gyro1|block": "gyro 1",
|
||||||
"sensors.gyro2|block": "gyro 2",
|
"sensors.gyro2|block": "gyro 2",
|
||||||
"sensors.gyro3|block": "gyro 3",
|
"sensors.gyro3|block": "gyro 3",
|
||||||
|
@ -8,16 +8,27 @@ namespace sensors {
|
|||||||
//% fixedInstances
|
//% fixedInstances
|
||||||
export class GyroSensor extends internal.UartSensor {
|
export class GyroSensor extends internal.UartSensor {
|
||||||
private calibrating: boolean;
|
private calibrating: boolean;
|
||||||
|
private _drift: number;
|
||||||
|
private _drifting: boolean;
|
||||||
constructor(port: number) {
|
constructor(port: number) {
|
||||||
super(port)
|
super(port)
|
||||||
this.calibrating = false;
|
this.calibrating = false;
|
||||||
|
this._drift = 0;
|
||||||
|
this._drifting = true;
|
||||||
|
this.setMode(GyroSensorMode.Rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
_deviceType() {
|
_deviceType() {
|
||||||
return DAL.DEVICE_TYPE_GYRO
|
return DAL.DEVICE_TYPE_GYRO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_query(): number {
|
||||||
|
return this.getNumber(NumberFormat.Int16LE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
setMode(m: GyroSensorMode) {
|
setMode(m: GyroSensorMode) {
|
||||||
|
if (m == GyroSensorMode.Rate && this.mode != m)
|
||||||
|
this._drift = 0;
|
||||||
this._setMode(m)
|
this._setMode(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,67 +42,97 @@ namespace sensors {
|
|||||||
//% parts="gyroscope"
|
//% parts="gyroscope"
|
||||||
//% blockNamespace=sensors
|
//% blockNamespace=sensors
|
||||||
//% sensor.fieldEditor="ports"
|
//% sensor.fieldEditor="ports"
|
||||||
//% weight=65 blockGap=8
|
//% weight=64 blockGap=8
|
||||||
//% group="Gyro Sensor"
|
//% group="Gyro Sensor"
|
||||||
angle(): number {
|
angle(): number {
|
||||||
if (this.calibrating)
|
if (this.calibrating)
|
||||||
pauseUntil(() => !this.calibrating, 2000);
|
pauseUntil(() => !this.calibrating, 2000);
|
||||||
|
|
||||||
this.setMode(GyroSensorMode.Angle)
|
this.setMode(GyroSensorMode.Angle);
|
||||||
return this.getNumber(NumberFormat.Int16LE, 0)
|
return this._query();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current rotation rate from the gyroscope.
|
* Get the current rotation rate from the gyroscope.
|
||||||
* @param sensor the gyroscope to query the request
|
* @param sensor the gyroscope to query the request
|
||||||
*/
|
*/
|
||||||
//% help=input/gyro/rotation-rate
|
//% help=input/gyro/rate
|
||||||
//% block="%sensor|rotation rate"
|
//% block="%sensor|rate"
|
||||||
//% blockId=gyroGetRate
|
//% blockId=gyroGetRate
|
||||||
//% parts="gyroscope"
|
//% parts="gyroscope"
|
||||||
//% blockNamespace=sensors
|
//% blockNamespace=sensors
|
||||||
//% sensor.fieldEditor="ports"
|
//% sensor.fieldEditor="ports"
|
||||||
//% weight=65 blockGap=8
|
//% weight=65 blockGap=8
|
||||||
//% group="Gyro Sensor"
|
//% group="Gyro Sensor"
|
||||||
rotationRate(): number {
|
rate(): number {
|
||||||
if (this.calibrating)
|
if (this.calibrating)
|
||||||
pauseUntil(() => !this.calibrating, 2000);
|
pauseUntil(() => !this.calibrating, 2000);
|
||||||
|
|
||||||
this.setMode(GyroSensorMode.Rate)
|
this.setMode(GyroSensorMode.Rate);
|
||||||
return this.getNumber(NumberFormat.Int16LE, 0)
|
let curr = this._query();
|
||||||
|
if (Math.abs(curr) < 20) {
|
||||||
|
const p = 0.0005;
|
||||||
|
this._drift = (1 - p) * this._drift + p * curr;
|
||||||
|
curr -= this._drift;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces a calibration of the gyro. Must be called when the sensor is completely still.
|
* Forces a calibration of the gyro. Must be called when the sensor is completely still.
|
||||||
*/
|
*/
|
||||||
//% help=input/gyro/calibrate
|
//% help=input/gyro/calibrate
|
||||||
//% block="%sensor|calibrate"
|
//% block="%sensor|reset"
|
||||||
//% blockId=gyroCalibrate
|
//% blockId=gyroReset
|
||||||
//% parts="gyroscope"
|
//% parts="gyroscope"
|
||||||
//% blockNamespace=sensors
|
//% blockNamespace=sensors
|
||||||
//% sensor.fieldEditor="ports"
|
//% sensor.fieldEditor="ports"
|
||||||
//% weight=65 blockGap=8
|
//% weight=50 blockGap=8
|
||||||
//% group="Gyro Sensor"
|
//% group="Gyro Sensor"
|
||||||
calibrate(): void {
|
reset(): void {
|
||||||
if (this.calibrating) return; // already in calibration mode
|
if (this.calibrating) return; // already in calibration mode
|
||||||
|
|
||||||
this.calibrating = true;
|
this.calibrating = true;
|
||||||
// may be triggered by a button click, give time to settle
|
// may be triggered by a button click,
|
||||||
loops.pause(500);
|
// give time for robot to settle
|
||||||
|
loops.pause(700);
|
||||||
// send a reset command
|
// send a reset command
|
||||||
this.reset();
|
super.reset();
|
||||||
// we need to switch mode twice to perform a calibration
|
// switch back to the desired mode
|
||||||
if (this.mode == GyroSensorMode.Rate)
|
this.setMode(this.mode);
|
||||||
this.setMode(GyroSensorMode.Angle);
|
// wait till sensor is live
|
||||||
else
|
pauseUntil(() => this.isActive());
|
||||||
this.setMode(GyroSensorMode.Rate);
|
// give it a bit of time to init
|
||||||
// switch back and wait
|
loops.pause(1000)
|
||||||
if (this.mode == GyroSensorMode.Rate)
|
// compute drift
|
||||||
this.setMode(GyroSensorMode.Angle);
|
this._drift = 0;
|
||||||
else
|
if (this.mode == GyroSensorMode.Rate) {
|
||||||
this.setMode(GyroSensorMode.Rate);
|
for (let i = 0; i < 200; ++i) {
|
||||||
|
this._drift += this._query();
|
||||||
|
loops.pause(4);
|
||||||
|
}
|
||||||
|
this._drift /= 200;
|
||||||
|
}
|
||||||
|
// and we're done
|
||||||
this.calibrating = false;
|
this.calibrating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the computed rate drift
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
drift(): number {
|
||||||
|
return this._drift;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disable drift correction
|
||||||
|
* @param enabled
|
||||||
|
*/
|
||||||
|
//%
|
||||||
|
setDriftCorrection(enabled: boolean) {
|
||||||
|
this._drifting = enabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//% fixedInstance whenUsed block="gyro 2" weight=95 jres=icons.port2
|
//% fixedInstance whenUsed block="gyro 2" weight=95 jres=icons.port2
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
"sensors.InfraredSensor.pauseUntil": "Waits for the event to occur",
|
"sensors.InfraredSensor.pauseUntil": "Waits for the event to occur",
|
||||||
"sensors.InfraredSensor.proximity": "Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)",
|
"sensors.InfraredSensor.proximity": "Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)",
|
||||||
"sensors.InfraredSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.",
|
"sensors.InfraredSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.",
|
||||||
|
"sensors.InfraredSensor.setThreshold": "Sets a threshold value",
|
||||||
|
"sensors.InfraredSensor.setThreshold|param|condition": "the dark or bright light condition",
|
||||||
|
"sensors.InfraredSensor.setThreshold|param|value": "the value threshold",
|
||||||
"sensors.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.",
|
"sensors.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.",
|
||||||
"sensors.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down",
|
"sensors.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down",
|
||||||
"sensors.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised",
|
"sensors.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised",
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"sensors.InfraredSensor.pauseUntil|block": "pause until %sensor| %event",
|
"sensors.InfraredSensor.pauseUntil|block": "pause until %sensor| %event",
|
||||||
"sensors.InfraredSensor.proximity|block": "%sensor|proximity",
|
"sensors.InfraredSensor.proximity|block": "%sensor|proximity",
|
||||||
"sensors.InfraredSensor.remoteCommand|block": "%sensor|remote command",
|
"sensors.InfraredSensor.remoteCommand|block": "%sensor|remote command",
|
||||||
|
"sensors.InfraredSensor.setThreshold|block": "set %sensor|%condition|to %value",
|
||||||
"sensors.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
|
"sensors.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
|
||||||
"sensors.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
|
"sensors.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
|
||||||
"sensors.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",
|
"sensors.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",
|
||||||
@ -20,5 +21,6 @@
|
|||||||
"sensors|block": "sensors",
|
"sensors|block": "sensors",
|
||||||
"{id:category}Sensors": "Sensors",
|
"{id:category}Sensors": "Sensors",
|
||||||
"{id:group}Infrared Sensor": "Infrared Sensor",
|
"{id:group}Infrared Sensor": "Infrared Sensor",
|
||||||
"{id:group}Remote Infrared Beacon": "Remote Infrared Beacon"
|
"{id:group}Remote Infrared Beacon": "Remote Infrared Beacon",
|
||||||
|
"{id:group}Threshold": "Threshold"
|
||||||
}
|
}
|
@ -250,6 +250,22 @@ namespace sensors {
|
|||||||
this._setMode(IrSensorMode.Seek)
|
this._setMode(IrSensorMode.Seek)
|
||||||
return this.getNumber(NumberFormat.UInt16LE, this.channel * 2)
|
return this.getNumber(NumberFormat.UInt16LE, this.channel * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a threshold value
|
||||||
|
* @param condition the dark or bright light condition
|
||||||
|
* @param value the value threshold
|
||||||
|
*/
|
||||||
|
//% blockId=irSetThreshold block="set %sensor|%condition|to %value"
|
||||||
|
//% group="Threshold" blockGap=8
|
||||||
|
//% value.min=0 value.max=100
|
||||||
|
setThreshold(condition: InfraredSensorEvent, value: number) {
|
||||||
|
if (condition == InfraredSensorEvent.ObjectNear)
|
||||||
|
this.proximityThreshold.setLowThreshold(value)
|
||||||
|
else
|
||||||
|
this.proximityThreshold.setHighThreshold(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//% fixedInstance whenUsed block="infrared 1" jres=icons.port1
|
//% fixedInstance whenUsed block="infrared 1" jres=icons.port1
|
||||||
|
3
libs/mood/README.md
Normal file
3
libs/mood/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# mood
|
||||||
|
|
||||||
|
A package to put the EV3 in various moods.
|
16
libs/mood/_locales/mood-jsdoc-strings.json
Normal file
16
libs/mood/_locales/mood-jsdoc-strings.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"brick.Mood": "A mood",
|
||||||
|
"brick.Mood.show": "Shows the mood on the EV3",
|
||||||
|
"brick.angry": "An angry mood",
|
||||||
|
"brick.awake": "A awake mood",
|
||||||
|
"brick.dizzy": "A dizzy mood",
|
||||||
|
"brick.knockedOut": "A knocked out mood",
|
||||||
|
"brick.love": "In love mood",
|
||||||
|
"brick.middleLeft": "Looking around left",
|
||||||
|
"brick.middleRight": "Looking around right",
|
||||||
|
"brick.neutral": "In a neutral mood",
|
||||||
|
"brick.sad": "A sad mood",
|
||||||
|
"brick.sleeping": "A sleeping mood",
|
||||||
|
"brick.tired": "A tired mood",
|
||||||
|
"brick.winking": "In laughing mood"
|
||||||
|
}
|
6
libs/mood/_locales/mood-strings.json
Normal file
6
libs/mood/_locales/mood-strings.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"brick.Mood.show|block": "show mood %mood=mood_image_picker",
|
||||||
|
"brick|block": "brick",
|
||||||
|
"{id:category}Brick": "Brick",
|
||||||
|
"{id:group}Screen": "Screen"
|
||||||
|
}
|
115
libs/mood/mood.ts
Normal file
115
libs/mood/mood.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
namespace brick {
|
||||||
|
/**
|
||||||
|
* A mood
|
||||||
|
*/
|
||||||
|
//% fixedInstances
|
||||||
|
export class Mood {
|
||||||
|
image: Image;
|
||||||
|
sound: Sound;
|
||||||
|
light: BrickLight;
|
||||||
|
|
||||||
|
constructor(image: Image, sound: Sound, light: BrickLight) {
|
||||||
|
this.image = image;
|
||||||
|
this.sound = sound;
|
||||||
|
this.light = light;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the mood on the EV3
|
||||||
|
*/
|
||||||
|
//% weight=90
|
||||||
|
//% blockId=moodShow block="show mood %mood=mood_image_picker"
|
||||||
|
//% weight=101 group="Screen" blockGap=8
|
||||||
|
show() {
|
||||||
|
brick.setLight(this.light);
|
||||||
|
brick.showImage(this.image);
|
||||||
|
if (this.sound)
|
||||||
|
music.playSoundEffect(this.sound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An image
|
||||||
|
* @param image the image
|
||||||
|
*/
|
||||||
|
//% blockId=mood_image_picker block="%image" shim=TD_ID
|
||||||
|
//% image.fieldEditor="images"
|
||||||
|
//% image.fieldOptions.columns=4
|
||||||
|
//% image.fieldOptions.width=400
|
||||||
|
//% group="Screen" weight=0 blockHidden=1
|
||||||
|
export function __moodImagePicker(mood: Mood): Mood {
|
||||||
|
return mood;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sleeping mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesSleeping
|
||||||
|
export const sleeping = new Mood(images.eyesSleeping, sounds.expressionsSnoring, BrickLight.OrangePulse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A awake mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesAwake
|
||||||
|
export const awake = new Mood(images.eyesAwake, sounds.informationActivate, BrickLight.Orange);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tired mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesTiredMiddle
|
||||||
|
export const tired = new Mood(images.eyesTiredMiddle, sounds.expressionsSneezing, BrickLight.OrangeFlash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An angry mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesAngry
|
||||||
|
export const angry = new Mood(images.eyesAngry, sounds.animalsDogGrowl, BrickLight.RedPulse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sad mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesTear
|
||||||
|
export const sad = new Mood(images.eyesTear, sounds.animalsDogWhine, BrickLight.Red);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dizzy mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesDizzy
|
||||||
|
export const dizzy = new Mood(images.eyesDizzy, sounds.expressionsUhOh, BrickLight.OrangeFlash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A knocked out mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesKnockedOut
|
||||||
|
export const knockedOut = new Mood(images.eyesKnockedOut, sounds.informationError, BrickLight.RedFlash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looking around left
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesMiddleLeft
|
||||||
|
export const middleLeft = new Mood(images.eyesMiddleLeft, sounds.informationAnalyze, BrickLight.Off);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looking around right
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesMiddleRight
|
||||||
|
export const middleRight = new Mood(images.eyesMiddleRight, sounds.informationAnalyze, BrickLight.Off);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In love mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesLove
|
||||||
|
export const love = new Mood(images.eyesLove, sounds.expressionsMagicWand, BrickLight.GreenPulse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In laughing mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesWinking
|
||||||
|
export const winking = new Mood(images.eyesWinking, sounds.expressionsLaughing1, BrickLight.GreenFlash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In a neutral mood
|
||||||
|
*/
|
||||||
|
//% fixedInstance jres=images.eyesNeutral
|
||||||
|
export const neutral = new Mood(images.eyesNeutral, undefined, BrickLight.Green);
|
||||||
|
}
|
14
libs/mood/pxt.json
Normal file
14
libs/mood/pxt.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "mood",
|
||||||
|
"description": "The EV3 mood library",
|
||||||
|
"files": [
|
||||||
|
"README.md",
|
||||||
|
"mood.ts"
|
||||||
|
],
|
||||||
|
"testFiles": [
|
||||||
|
],
|
||||||
|
"public": true,
|
||||||
|
"dependencies": {
|
||||||
|
"core": "file:../core"
|
||||||
|
}
|
||||||
|
}
|
@ -33,34 +33,34 @@
|
|||||||
"music.stopAllSounds|block": "stop all sounds",
|
"music.stopAllSounds|block": "stop all sounds",
|
||||||
"music.tempo|block": "tempo (bpm)",
|
"music.tempo|block": "tempo (bpm)",
|
||||||
"music|block": "music",
|
"music|block": "music",
|
||||||
"sounds.animalsCatPurr|block": "Animals cat purr",
|
"sounds.animalsCatPurr|block": "animals cat purr",
|
||||||
"sounds.animalsDogBark1|block": "Animals dog bark 1",
|
"sounds.animalsDogBark1|block": "animals dog bark 1",
|
||||||
"sounds.animalsDogBark2|block": "Animals dog bark 2",
|
"sounds.animalsDogBark2|block": "animals dog bark 2",
|
||||||
"sounds.animalsDogGrowl|block": "Animals dog growl",
|
"sounds.animalsDogGrowl|block": "animals dog growl",
|
||||||
"sounds.animalsDogSniff|block": "Animals dog sniff",
|
"sounds.animalsDogSniff|block": "animals dog sniff",
|
||||||
"sounds.animalsDogWhine|block": "Animals dog whine",
|
"sounds.animalsDogWhine|block": "animals dog whine",
|
||||||
"sounds.animalsElephantCall|block": "Animals elephant call",
|
"sounds.animalsElephantCall|block": "animals elephant call",
|
||||||
"sounds.animalsInsectBuzz1|block": "Animals insect buzz1",
|
"sounds.animalsInsectBuzz1|block": "animals insect buzz1",
|
||||||
"sounds.animalsInsectBuzz2|block": "Animals insect buzz2",
|
"sounds.animalsInsectBuzz2|block": "animals insect buzz2",
|
||||||
"sounds.animalsInsectChirp|block": "Animals insect chirp",
|
"sounds.animalsInsectChirp|block": "animals insect chirp",
|
||||||
"sounds.animalsSnakeHiss|block": "Animals snake hiss",
|
"sounds.animalsSnakeHiss|block": "animals snake hiss",
|
||||||
"sounds.animalsSnakeRattle|block": "Animals snake rattle",
|
"sounds.animalsSnakeRattle|block": "animals snake rattle",
|
||||||
"sounds.animalsTRexRoar|block": "Animals trex roar",
|
"sounds.animalsTRexRoar|block": "animals trex roar",
|
||||||
"sounds.colorsBlack|block": "Colors black",
|
"sounds.colorsBlack|block": "colors black",
|
||||||
"sounds.colorsBlue|block": "Colors blue",
|
"sounds.colorsBlue|block": "colors blue",
|
||||||
"sounds.colorsBrown|block": "Colors brown",
|
"sounds.colorsBrown|block": "colors brown",
|
||||||
"sounds.colorsGreen|block": "Colors green",
|
"sounds.colorsGreen|block": "colors green",
|
||||||
"sounds.colorsRed|block": "Colors red",
|
"sounds.colorsRed|block": "colors red",
|
||||||
"sounds.colorsWhite|block": "Colors white",
|
"sounds.colorsWhite|block": "colors white",
|
||||||
"sounds.colorsYellow|block": "Colors yellow",
|
"sounds.colorsYellow|block": "colors yellow",
|
||||||
"sounds.communicationBravo|block": "Communication bravo",
|
"sounds.communicationBravo|block": "communication bravo",
|
||||||
"sounds.communicationEv3|block": "Communication ev3",
|
"sounds.communicationEv3|block": "communication ev3",
|
||||||
"sounds.communicationFantastic|block": "Communication fantastic",
|
"sounds.communicationFantastic|block": "communication fantastic",
|
||||||
"sounds.communicationGameOver|block": "Communication game over",
|
"sounds.communicationGameOver|block": "communication game over",
|
||||||
"sounds.communicationGoodJob|block": "communicationGoodJob",
|
"sounds.communicationGoodJob|block": "communicationGoodJob",
|
||||||
"sounds.communicationGoodbye|block": "communication goodbye",
|
"sounds.communicationGoodbye|block": "communication goodbye",
|
||||||
"sounds.communicationGood|block": "communication good",
|
"sounds.communicationGood|block": "communication good",
|
||||||
"sounds.communicationGo|block": "Communication go",
|
"sounds.communicationGo|block": "communication go",
|
||||||
"sounds.communicationHello|block": "communication hello",
|
"sounds.communicationHello|block": "communication hello",
|
||||||
"sounds.communicationHi|block": "communication hi",
|
"sounds.communicationHi|block": "communication hi",
|
||||||
"sounds.communicationLego|block": "communication lego",
|
"sounds.communicationLego|block": "communication lego",
|
||||||
@ -121,7 +121,7 @@
|
|||||||
"sounds.mechanicalMotorStart|block": "mechanical motor start",
|
"sounds.mechanicalMotorStart|block": "mechanical motor start",
|
||||||
"sounds.mechanicalMotorStop|block": "mechanical motor stop",
|
"sounds.mechanicalMotorStop|block": "mechanical motor stop",
|
||||||
"sounds.mechanicalRatchet|block": "mechanical ratchet",
|
"sounds.mechanicalRatchet|block": "mechanical ratchet",
|
||||||
"sounds.mechanicalSonar|block": "\"mechanical sonar\"",
|
"sounds.mechanicalSonar|block": "mechanical sonar",
|
||||||
"sounds.mechanicalTickTack|block": "mechanical tick tack",
|
"sounds.mechanicalTickTack|block": "mechanical tick tack",
|
||||||
"sounds.mechanicalWalk|block": "mechanical walk",
|
"sounds.mechanicalWalk|block": "mechanical walk",
|
||||||
"sounds.movementsArm1|block": "movements arm1",
|
"sounds.movementsArm1|block": "movements arm1",
|
||||||
@ -159,7 +159,7 @@
|
|||||||
"sounds.systemOverpower|block": "system overpower",
|
"sounds.systemOverpower|block": "system overpower",
|
||||||
"sounds.systemPowerDown|block": "system power down",
|
"sounds.systemPowerDown|block": "system power down",
|
||||||
"sounds.systemReady|block": "system ready",
|
"sounds.systemReady|block": "system ready",
|
||||||
"sounds.systemStartUp|block": "S",
|
"sounds.systemStartUp|block": "system start up",
|
||||||
"{id:category}Music": "Music",
|
"{id:category}Music": "Music",
|
||||||
"{id:category}Sound": "Sound",
|
"{id:category}Sound": "Sound",
|
||||||
"{id:category}Sounds": "Sounds"
|
"{id:category}Sounds": "Sounds"
|
||||||
|
@ -1,53 +1,53 @@
|
|||||||
namespace sounds {
|
namespace sounds {
|
||||||
//% fixedInstance jres block="Animals cat purr"
|
//% fixedInstance jres block="animals cat purr"
|
||||||
export const animalsCatPurr = music.fromWAV(hex``);
|
export const animalsCatPurr = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals dog bark 1"
|
//% fixedInstance jres block="animals dog bark 1"
|
||||||
export const animalsDogBark1 = music.fromWAV(hex``);
|
export const animalsDogBark1 = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals dog bark 2"
|
//% fixedInstance jres block="animals dog bark 2"
|
||||||
export const animalsDogBark2 = music.fromWAV(hex``);
|
export const animalsDogBark2 = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals dog growl"
|
//% fixedInstance jres block="animals dog growl"
|
||||||
export const animalsDogGrowl = music.fromWAV(hex``);
|
export const animalsDogGrowl = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals dog sniff"
|
//% fixedInstance jres block="animals dog sniff"
|
||||||
export const animalsDogSniff = music.fromWAV(hex``);
|
export const animalsDogSniff = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals dog whine"
|
//% fixedInstance jres block="animals dog whine"
|
||||||
export const animalsDogWhine = music.fromWAV(hex``);
|
export const animalsDogWhine = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals elephant call"
|
//% fixedInstance jres block="animals elephant call"
|
||||||
export const animalsElephantCall = music.fromWAV(hex``);
|
export const animalsElephantCall = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals insect buzz1"
|
//% fixedInstance jres block="animals insect buzz1"
|
||||||
export const animalsInsectBuzz1 = music.fromWAV(hex``);
|
export const animalsInsectBuzz1 = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals insect buzz2"
|
//% fixedInstance jres block="animals insect buzz2"
|
||||||
export const animalsInsectBuzz2 = music.fromWAV(hex``);
|
export const animalsInsectBuzz2 = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals insect chirp"
|
//% fixedInstance jres block="animals insect chirp"
|
||||||
export const animalsInsectChirp = music.fromWAV(hex``);
|
export const animalsInsectChirp = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals snake hiss"
|
//% fixedInstance jres block="animals snake hiss"
|
||||||
export const animalsSnakeHiss = music.fromWAV(hex``);
|
export const animalsSnakeHiss = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals snake rattle"
|
//% fixedInstance jres block="animals snake rattle"
|
||||||
export const animalsSnakeRattle = music.fromWAV(hex``);
|
export const animalsSnakeRattle = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Animals trex roar"
|
//% fixedInstance jres block="animals trex roar"
|
||||||
export const animalsTRexRoar = music.fromWAV(hex``);
|
export const animalsTRexRoar = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors black"
|
//% fixedInstance jres block="colors black"
|
||||||
export const colorsBlack = music.fromWAV(hex``);
|
export const colorsBlack = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors blue"
|
//% fixedInstance jres block="colors blue"
|
||||||
export const colorsBlue = music.fromWAV(hex``);
|
export const colorsBlue = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors brown"
|
//% fixedInstance jres block="colors brown"
|
||||||
export const colorsBrown = music.fromWAV(hex``);
|
export const colorsBrown = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors green"
|
//% fixedInstance jres block="colors green"
|
||||||
export const colorsGreen = music.fromWAV(hex``);
|
export const colorsGreen = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors red"
|
//% fixedInstance jres block="colors red"
|
||||||
export const colorsRed = music.fromWAV(hex``);
|
export const colorsRed = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors white"
|
//% fixedInstance jres block="colors white"
|
||||||
export const colorsWhite = music.fromWAV(hex``);
|
export const colorsWhite = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Colors yellow"
|
//% fixedInstance jres block="colors yellow"
|
||||||
export const colorsYellow = music.fromWAV(hex``);
|
export const colorsYellow = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Communication bravo"
|
//% fixedInstance jres block="communication bravo"
|
||||||
export const communicationBravo = music.fromWAV(hex``);
|
export const communicationBravo = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Communication ev3"
|
//% fixedInstance jres block="communication ev3"
|
||||||
export const communicationEv3 = music.fromWAV(hex``);
|
export const communicationEv3 = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Communication fantastic"
|
//% fixedInstance jres block="communication fantastic"
|
||||||
export const communicationFantastic = music.fromWAV(hex``);
|
export const communicationFantastic = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Communication game over"
|
//% fixedInstance jres block="communication game over"
|
||||||
export const communicationGameOver = music.fromWAV(hex``);
|
export const communicationGameOver = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="Communication go"
|
//% fixedInstance jres block="communication go"
|
||||||
export const communicationGo = music.fromWAV(hex``);
|
export const communicationGo = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="communicationGoodJob"
|
//% fixedInstance jres block="communicationGoodJob"
|
||||||
export const communicationGoodJob = music.fromWAV(hex``);
|
export const communicationGoodJob = music.fromWAV(hex``);
|
||||||
@ -175,7 +175,7 @@ namespace sounds {
|
|||||||
export const mechanicalMotorStop = music.fromWAV(hex``);
|
export const mechanicalMotorStop = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="mechanical ratchet"
|
//% fixedInstance jres block="mechanical ratchet"
|
||||||
export const mechanicalRatchet = music.fromWAV(hex``);
|
export const mechanicalRatchet = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block='"mechanical sonar"'
|
//% fixedInstance jres block="mechanical sonar"
|
||||||
export const mechanicalSonar = music.fromWAV(hex``);
|
export const mechanicalSonar = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="mechanical tick tack"
|
//% fixedInstance jres block="mechanical tick tack"
|
||||||
export const mechanicalTickTack = music.fromWAV(hex``);
|
export const mechanicalTickTack = music.fromWAV(hex``);
|
||||||
@ -251,7 +251,7 @@ namespace sounds {
|
|||||||
export const systemPowerDown = music.fromWAV(hex``);
|
export const systemPowerDown = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block="system ready"
|
//% fixedInstance jres block="system ready"
|
||||||
export const systemReady = music.fromWAV(hex``);
|
export const systemReady = music.fromWAV(hex``);
|
||||||
//% fixedInstance jres block=S
|
//% fixedInstance jres block="system start up"
|
||||||
export const systemStartUp = music.fromWAV(hex``);
|
export const systemStartUp = music.fromWAV(hex``);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
libs/storage/_locales/storage-jsdoc-strings.json
Normal file
29
libs/storage/_locales/storage-jsdoc-strings.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"storage.Storage.append": "Append string data to a new or existing file.",
|
||||||
|
"storage.Storage.appendBuffer": "Append a buffer to a new or existing file.",
|
||||||
|
"storage.Storage.appendCSV": "Append a row of CSV data",
|
||||||
|
"storage.Storage.appendCSVHeaders": "Append a row of CSV headers",
|
||||||
|
"storage.Storage.appendCSVHeaders|param|filename": "the file name to append data, eg: \"data.csv\"",
|
||||||
|
"storage.Storage.appendCSVHeaders|param|headers": "the data to append",
|
||||||
|
"storage.Storage.appendCSV|param|data": "the data to append",
|
||||||
|
"storage.Storage.appendCSV|param|filename": "the file name to append data, eg: \"data.csv\"",
|
||||||
|
"storage.Storage.appendLine": "Appends a new line of data in the file",
|
||||||
|
"storage.Storage.appendLine|param|data": "the data to append",
|
||||||
|
"storage.Storage.appendLine|param|filename": "the file name to append data, eg: \"data.txt\"",
|
||||||
|
"storage.Storage.append|param|data": "the data to append",
|
||||||
|
"storage.Storage.append|param|filename": "the file name to append data, eg: \"data.txt\"",
|
||||||
|
"storage.Storage.exists": "Tests if a file exists",
|
||||||
|
"storage.Storage.exists|param|filename": "the file name to append data, eg: \"data.txt\"",
|
||||||
|
"storage.Storage.limit": "Resizing the size of a file to stay under the limit",
|
||||||
|
"storage.Storage.limit|param|filename": "name of the file to drop",
|
||||||
|
"storage.Storage.limit|param|size": "maximum length",
|
||||||
|
"storage.Storage.overwrite": "Overwrite file with string data.",
|
||||||
|
"storage.Storage.overwriteWithBuffer": "Overwrite file with a buffer.",
|
||||||
|
"storage.Storage.overwrite|param|data": "the data to append",
|
||||||
|
"storage.Storage.overwrite|param|filename": "the file name to append data, eg: \"data.txt\"",
|
||||||
|
"storage.Storage.read": "Read contents of file as a string.",
|
||||||
|
"storage.Storage.readAsBuffer": "Read contents of file as a buffer.",
|
||||||
|
"storage.Storage.remove": "Delete a file, or do nothing if it doesn't exist.",
|
||||||
|
"storage.Storage.size": "Return the size of the file, or -1 if it doesn't exists.",
|
||||||
|
"storage.temporary": "Temporary storage in memory, deleted when the device restarts."
|
||||||
|
}
|
15
libs/storage/_locales/storage-strings.json
Normal file
15
libs/storage/_locales/storage-strings.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"storage.Storage.appendCSVHeaders|block": "storage %source|%filename|append CSV headers %headers",
|
||||||
|
"storage.Storage.appendCSV|block": "storage %source|%filename|append CSV %data",
|
||||||
|
"storage.Storage.appendLine|block": "storage %source|%filename|append line %data",
|
||||||
|
"storage.Storage.append|block": "storage %source|%filename|append %data",
|
||||||
|
"storage.Storage.exists|block": "storage %source|%filename|exists",
|
||||||
|
"storage.Storage.limit|block": "storage %source|limit %filename|to %size|bytes",
|
||||||
|
"storage.Storage.overwrite|block": "storage %source|%filename|overwrite with|%data",
|
||||||
|
"storage.Storage.read|block": "storage %source|read %filename|as string",
|
||||||
|
"storage.Storage.remove|block": "storage %source|remove %filename",
|
||||||
|
"storage.Storage.size|block": "storage %source|%filename|size",
|
||||||
|
"storage.temporary|block": "temporary",
|
||||||
|
"storage|block": "storage",
|
||||||
|
"{id:category}Storage": "Storage"
|
||||||
|
}
|
14
libs/storage/pxt.json
Normal file
14
libs/storage/pxt.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "storage",
|
||||||
|
"description": "USB Pen-drive support and flash storage",
|
||||||
|
"files": [
|
||||||
|
"storage.cpp",
|
||||||
|
"storage-core.ts",
|
||||||
|
"storage.ts",
|
||||||
|
"shims.d.ts"
|
||||||
|
],
|
||||||
|
"public": true,
|
||||||
|
"dependencies": {
|
||||||
|
"core": "file:../core"
|
||||||
|
}
|
||||||
|
}
|
17
libs/storage/shims.d.ts
vendored
Normal file
17
libs/storage/shims.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Auto-generated. Do not edit.
|
||||||
|
declare namespace storage {
|
||||||
|
|
||||||
|
/** Will be moved. */
|
||||||
|
//% shim=storage::__stringToBuffer
|
||||||
|
function __stringToBuffer(s: string): Buffer;
|
||||||
|
|
||||||
|
/** Will be moved. */
|
||||||
|
//% shim=storage::__bufferToString
|
||||||
|
function __bufferToString(s: Buffer): string;
|
||||||
|
|
||||||
|
/** Create named directory. */
|
||||||
|
//% shim=storage::__mkdir
|
||||||
|
function __mkdir(filename: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-generated. Do not edit. Really.
|
202
libs/storage/storage-core.ts
Normal file
202
libs/storage/storage-core.ts
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
namespace storage {
|
||||||
|
//% shim=storage::__unlink
|
||||||
|
function __unlink(filename: string): void { }
|
||||||
|
//% shim=storage::__truncate
|
||||||
|
function __truncate(filename: string): void { }
|
||||||
|
|
||||||
|
//% fixedInstances
|
||||||
|
export class Storage {
|
||||||
|
csvSeparator: string;
|
||||||
|
constructor() {
|
||||||
|
this.csvSeparator = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected mapFilename(filename: string) {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getFile(filename: string): MMap {
|
||||||
|
filename = this.mapFilename(filename)
|
||||||
|
let r = control.mmap(filename, 0, 0)
|
||||||
|
if (!r) {
|
||||||
|
__mkdir(this.dirname(filename))
|
||||||
|
__truncate(filename)
|
||||||
|
r = control.mmap(filename, 0, 0)
|
||||||
|
}
|
||||||
|
if (!r)
|
||||||
|
control.panic(906)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
dirname(filename: string) {
|
||||||
|
let last = 0
|
||||||
|
for (let i = 0; i < filename.length; ++i)
|
||||||
|
if (filename[i] == "/")
|
||||||
|
last = i
|
||||||
|
return filename.substr(0, last)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append string data to a new or existing file.
|
||||||
|
* @param filename the file name to append data, eg: "data.txt"
|
||||||
|
* @param data the data to append
|
||||||
|
*/
|
||||||
|
//% blockId=storageAppend block="storage %source|%filename|append %data"
|
||||||
|
append(filename: string, data: string): void {
|
||||||
|
this.appendBuffer(filename, __stringToBuffer(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a new line of data in the file
|
||||||
|
* @param filename the file name to append data, eg: "data.txt"
|
||||||
|
* @param data the data to append
|
||||||
|
*/
|
||||||
|
//% blockId=storageAppendLine block="storage %source|%filename|append line %data"
|
||||||
|
appendLine(filename: string, data: string): void {
|
||||||
|
this.append(filename, data + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Append a buffer to a new or existing file. */
|
||||||
|
appendBuffer(filename: string, data: Buffer): void {
|
||||||
|
let f = this.getFile(filename);
|
||||||
|
f.lseek(0, SeekWhence.End)
|
||||||
|
f.write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a row of CSV headers
|
||||||
|
* @param filename the file name to append data, eg: "data.csv"
|
||||||
|
* @param headers the data to append
|
||||||
|
*/
|
||||||
|
//% blockId=storageAppendCSVHeaders block="storage %source|%filename|append CSV headers %headers"
|
||||||
|
appendCSVHeaders(filename: string, headers: string[]) {
|
||||||
|
let s = ""
|
||||||
|
for (const d of headers) {
|
||||||
|
if (s) s += this.csvSeparator;
|
||||||
|
s = s + d;
|
||||||
|
}
|
||||||
|
s += "\r\n"
|
||||||
|
this.append(filename, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a row of CSV data
|
||||||
|
* @param filename the file name to append data, eg: "data.csv"
|
||||||
|
* @param data the data to append
|
||||||
|
*/
|
||||||
|
//% blockId=storageAppendCSV block="storage %source|%filename|append CSV %data"
|
||||||
|
appendCSV(filename: string, data: number[]) {
|
||||||
|
let s = toCSV(data, this.csvSeparator);
|
||||||
|
this.append(filename, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Overwrite file with string data.
|
||||||
|
* @param filename the file name to append data, eg: "data.txt"
|
||||||
|
* @param data the data to append
|
||||||
|
*/
|
||||||
|
//% blockId=storageOverwrite block="storage %source|%filename|overwrite with|%data"
|
||||||
|
overwrite(filename: string, data: string): void {
|
||||||
|
this.overwriteWithBuffer(filename, __stringToBuffer(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Overwrite file with a buffer. */
|
||||||
|
overwriteWithBuffer(filename: string, data: Buffer): void {
|
||||||
|
__truncate(this.mapFilename(filename))
|
||||||
|
this.appendBuffer(filename, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tests if a file exists
|
||||||
|
* @param filename the file name to append data, eg: "data.txt"
|
||||||
|
*/
|
||||||
|
//% blockId=storageExists block="storage %source|%filename|exists"
|
||||||
|
exists(filename: string): boolean {
|
||||||
|
return !!control.mmap(this.mapFilename(filename), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Delete a file, or do nothing if it doesn't exist. */
|
||||||
|
//% blockId=storageRemove block="storage %source|remove %filename"
|
||||||
|
remove(filename: string): void {
|
||||||
|
__unlink(this.mapFilename(filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the size of the file, or -1 if it doesn't exists. */
|
||||||
|
//% blockId=storageSize block="storage %source|%filename|size"
|
||||||
|
size(filename: string): int32 {
|
||||||
|
let f = control.mmap(this.mapFilename(filename), 0, 0)
|
||||||
|
if (!f) return -1;
|
||||||
|
return f.lseek(0, SeekWhence.End)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read contents of file as a string. */
|
||||||
|
//% blockId=storageRead block="storage %source|read %filename|as string"
|
||||||
|
read(filename: string): string {
|
||||||
|
return __bufferToString(this.readAsBuffer(filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read contents of file as a buffer. */
|
||||||
|
//%
|
||||||
|
readAsBuffer(filename: string): Buffer {
|
||||||
|
let f = this.getFile(filename)
|
||||||
|
let sz = f.lseek(0, SeekWhence.End)
|
||||||
|
let b = output.createBuffer(sz)
|
||||||
|
f.lseek(0, SeekWhence.Set);
|
||||||
|
f.read(b)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizing the size of a file to stay under the limit
|
||||||
|
* @param filename name of the file to drop
|
||||||
|
* @param size maximum length
|
||||||
|
*/
|
||||||
|
//% blockId=storageLimit block="storage %source|limit %filename|to %size|bytes"
|
||||||
|
limit(filename: string, size: number) {
|
||||||
|
if (!this.exists(filename) || size < 0) return;
|
||||||
|
|
||||||
|
const sz = storage.temporary.size(filename);
|
||||||
|
if (sz > size) {
|
||||||
|
let buf = storage.temporary.readAsBuffer(filename)
|
||||||
|
buf = buf.slice(buf.length / 2);
|
||||||
|
storage.temporary.overwriteWithBuffer(filename, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toCSV(data: number[], sep: string) {
|
||||||
|
let s = ""
|
||||||
|
for (const d of data) {
|
||||||
|
if (s) s += sep;
|
||||||
|
s = s + d;
|
||||||
|
}
|
||||||
|
s += "\r\n"
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemporaryStorage extends Storage {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected mapFilename(filename: string) {
|
||||||
|
if (filename[0] == '/') filename = filename.substr(1);
|
||||||
|
return '/tmp/logs/' + filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary storage in memory, deleted when the device restarts.
|
||||||
|
*/
|
||||||
|
//% whenUsed fixedInstance block="temporary"
|
||||||
|
export const temporary: Storage = new TemporaryStorage();
|
||||||
|
|
||||||
|
class PermanentStorage extends Storage {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected mapFilename(filename: string) {
|
||||||
|
if (filename[0] == '/') return filename;
|
||||||
|
return '/' + filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
libs/storage/storage.cpp
Normal file
44
libs/storage/storage.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "pxt.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
namespace storage {
|
||||||
|
|
||||||
|
/** Will be moved. */
|
||||||
|
//%
|
||||||
|
Buffer __stringToBuffer(String s) {
|
||||||
|
return mkBuffer((uint8_t *)s->data, s->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Will be moved. */
|
||||||
|
//%
|
||||||
|
String __bufferToString(Buffer s) {
|
||||||
|
return mkString((char*)s->data, s->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
void __init() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
void __unlink(String filename) {
|
||||||
|
::unlink(filename->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
void __truncate(String filename) {
|
||||||
|
int fd = open(filename->data, O_CREAT | O_TRUNC | O_WRONLY, 0777);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create named directory. */
|
||||||
|
//%
|
||||||
|
void __mkdir(String filename) {
|
||||||
|
::mkdir(filename->data, 0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace storage
|
11
libs/storage/storage.ts
Normal file
11
libs/storage/storage.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace storage {
|
||||||
|
// automatically send console output to temp storage
|
||||||
|
storage.temporary.remove("console.txt");
|
||||||
|
console.addListener(function(line) {
|
||||||
|
const fn = "console.txt";
|
||||||
|
const mxs = 65536;
|
||||||
|
const t = control.millis();
|
||||||
|
storage.temporary.appendLine(fn, `${t}> ${line}`);
|
||||||
|
storage.temporary.limit(fn, 65536);
|
||||||
|
})
|
||||||
|
}
|
@ -2,5 +2,8 @@
|
|||||||
"sensors.UltraSonicSensor.distance": "Gets the distance from the sonar in centimeters",
|
"sensors.UltraSonicSensor.distance": "Gets the distance from the sonar in centimeters",
|
||||||
"sensors.UltraSonicSensor.onEvent": "Registers code to run when the given color is close",
|
"sensors.UltraSonicSensor.onEvent": "Registers code to run when the given color is close",
|
||||||
"sensors.UltraSonicSensor.onEvent|param|handler": "the code to run when detected",
|
"sensors.UltraSonicSensor.onEvent|param|handler": "the code to run when detected",
|
||||||
"sensors.UltraSonicSensor.pauseUntil": "Waits for the event to occur"
|
"sensors.UltraSonicSensor.pauseUntil": "Waits for the event to occur",
|
||||||
|
"sensors.UltraSonicSensor.setThreshold": "Sets a threshold value",
|
||||||
|
"sensors.UltraSonicSensor.setThreshold|param|condition": "the dark or bright light condition",
|
||||||
|
"sensors.UltraSonicSensor.setThreshold|param|value": "the value threshold"
|
||||||
}
|
}
|
@ -5,10 +5,12 @@
|
|||||||
"sensors.UltraSonicSensor.distance|block": "%sensor|distance",
|
"sensors.UltraSonicSensor.distance|block": "%sensor|distance",
|
||||||
"sensors.UltraSonicSensor.onEvent|block": "on %sensor|%event",
|
"sensors.UltraSonicSensor.onEvent|block": "on %sensor|%event",
|
||||||
"sensors.UltraSonicSensor.pauseUntil|block": "pause until %sensor| %event",
|
"sensors.UltraSonicSensor.pauseUntil|block": "pause until %sensor| %event",
|
||||||
|
"sensors.UltraSonicSensor.setThreshold|block": "set %sensor|%condition|to %value",
|
||||||
"sensors.ultrasonic1|block": "ultrasonic 1",
|
"sensors.ultrasonic1|block": "ultrasonic 1",
|
||||||
"sensors.ultrasonic2|block": "ultrasonic 2",
|
"sensors.ultrasonic2|block": "ultrasonic 2",
|
||||||
"sensors.ultrasonic3|block": "ultrasonic 3",
|
"sensors.ultrasonic3|block": "ultrasonic 3",
|
||||||
"sensors.ultrasonic4|block": "ultrasonic 4",
|
"sensors.ultrasonic4|block": "ultrasonic 4",
|
||||||
"{id:category}Sensors": "Sensors",
|
"{id:category}Sensors": "Sensors",
|
||||||
|
"{id:group}Threshold": "Threshold",
|
||||||
"{id:group}Ultrasonic Sensor": "Ultrasonic Sensor"
|
"{id:group}Ultrasonic Sensor": "Ultrasonic Sensor"
|
||||||
}
|
}
|
@ -85,6 +85,23 @@ namespace sensors {
|
|||||||
this._setMode(0)
|
this._setMode(0)
|
||||||
return this._query();
|
return this._query();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a threshold value
|
||||||
|
* @param condition the dark or bright light condition
|
||||||
|
* @param value the value threshold
|
||||||
|
*/
|
||||||
|
//% blockId=ultrasonicSetThreshold block="set %sensor|%condition|to %value"
|
||||||
|
//% group="Threshold" blockGap=8
|
||||||
|
//% value.min=0 value.max=255
|
||||||
|
setThreshold(condition: UltrasonicSensorEvent, value: number) {
|
||||||
|
switch(condition) {
|
||||||
|
case UltrasonicSensorEvent.ObjectNear: this.promixityThreshold.setLowThreshold(value); break;
|
||||||
|
case UltrasonicSensorEvent.ObjectFar: this.promixityThreshold.setHighThreshold(value); break;
|
||||||
|
case UltrasonicSensorEvent.ObjectDetected: this.movementThreshold = value; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//% fixedInstance whenUsed block="ultrasonic 4" jres=icons.port4
|
//% fixedInstance whenUsed block="ultrasonic 4" jres=icons.port4
|
||||||
|
87
package-lock.json
generated
87
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-ev3",
|
"name": "pxt-ev3",
|
||||||
"version": "0.0.51",
|
"version": "0.0.64",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -399,7 +399,7 @@
|
|||||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "4.11.8",
|
"bn.js": "4.11.8",
|
||||||
"randombytes": "2.0.5"
|
"randombytes": "2.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-sign": {
|
"browserify-sign": {
|
||||||
@ -792,7 +792,7 @@
|
|||||||
"inherits": "2.0.3",
|
"inherits": "2.0.3",
|
||||||
"pbkdf2": "3.0.14",
|
"pbkdf2": "3.0.14",
|
||||||
"public-encrypt": "4.0.0",
|
"public-encrypt": "4.0.0",
|
||||||
"randombytes": "2.0.5",
|
"randombytes": "2.0.6",
|
||||||
"randomfill": "1.0.3"
|
"randomfill": "1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -956,7 +956,7 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "4.11.8",
|
"bn.js": "4.11.8",
|
||||||
"miller-rabin": "4.0.1",
|
"miller-rabin": "4.0.1",
|
||||||
"randombytes": "2.0.5"
|
"randombytes": "2.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domain-browser": {
|
"domain-browser": {
|
||||||
@ -1009,9 +1009,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"end-of-stream": {
|
"end-of-stream": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
|
||||||
"integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=",
|
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"once": "1.4.0"
|
"once": "1.4.0"
|
||||||
}
|
}
|
||||||
@ -1562,6 +1562,15 @@
|
|||||||
"verror": "1.10.0"
|
"verror": "1.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keytar": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/keytar/-/keytar-3.0.2.tgz",
|
||||||
|
"integrity": "sha1-TcFd01I/4wYx+dOIV4pAFRpgWG8=",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"nan": "2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
||||||
@ -1833,9 +1842,9 @@
|
|||||||
"integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI="
|
"integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI="
|
||||||
},
|
},
|
||||||
"marked": {
|
"marked": {
|
||||||
"version": "0.3.9",
|
"version": "0.3.12",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz",
|
||||||
"integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw=="
|
"integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA=="
|
||||||
},
|
},
|
||||||
"math-expression-evaluator": {
|
"math-expression-evaluator": {
|
||||||
"version": "1.2.17",
|
"version": "1.2.17",
|
||||||
@ -1966,8 +1975,7 @@
|
|||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.3.2.tgz",
|
||||||
"integrity": "sha1-TU7PF+HaTpie+08nPY0AIBytCH4=",
|
"integrity": "sha1-TU7PF+HaTpie+08nPY0AIBytCH4="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"neatequal": {
|
"neatequal": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -2510,7 +2518,7 @@
|
|||||||
"npmlog": "4.1.2",
|
"npmlog": "4.1.2",
|
||||||
"os-homedir": "1.0.2",
|
"os-homedir": "1.0.2",
|
||||||
"pump": "1.0.3",
|
"pump": "1.0.3",
|
||||||
"rc": "1.2.2",
|
"rc": "1.2.3",
|
||||||
"simple-get": "1.4.3",
|
"simple-get": "1.4.3",
|
||||||
"tar-fs": "1.16.0",
|
"tar-fs": "1.16.0",
|
||||||
"tunnel-agent": "0.6.0",
|
"tunnel-agent": "0.6.0",
|
||||||
@ -2558,7 +2566,7 @@
|
|||||||
"browserify-rsa": "4.0.1",
|
"browserify-rsa": "4.0.1",
|
||||||
"create-hash": "1.1.3",
|
"create-hash": "1.1.3",
|
||||||
"parse-asn1": "5.1.0",
|
"parse-asn1": "5.1.0",
|
||||||
"randombytes": "2.0.5"
|
"randombytes": "2.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pump": {
|
"pump": {
|
||||||
@ -2566,7 +2574,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
|
||||||
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
|
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"end-of-stream": "1.4.0",
|
"end-of-stream": "1.4.1",
|
||||||
"once": "1.4.0"
|
"once": "1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2576,19 +2584,19 @@
|
|||||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||||
},
|
},
|
||||||
"pxt-common-packages": {
|
"pxt-common-packages": {
|
||||||
"version": "0.14.13",
|
"version": "0.15.4",
|
||||||
"resolved": "https://registry.npmjs.org/pxt-common-packages/-/pxt-common-packages-0.14.13.tgz",
|
"resolved": "https://registry.npmjs.org/pxt-common-packages/-/pxt-common-packages-0.15.4.tgz",
|
||||||
"integrity": "sha1-L/axrdv7I1g6xjGC8JXNx/Bv0Ss=",
|
"integrity": "sha1-hI1q5+UQ7vIuBqlOrIy66PmiePo=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"autoprefixer": "6.7.7",
|
"autoprefixer": "6.7.7",
|
||||||
"pxt-core": "3.0.2",
|
"pxt-core": "3.0.8",
|
||||||
"rtlcss": "2.2.1"
|
"rtlcss": "2.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pxt-core": {
|
"pxt-core": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/pxt-core/-/pxt-core-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/pxt-core/-/pxt-core-3.0.8.tgz",
|
||||||
"integrity": "sha1-q7aCkAXRwvsmhPaeHR1S9osLK98=",
|
"integrity": "sha1-wmvgLvyX1lV5ZB6EM9APj22/gIo=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bluebird": "3.5.1",
|
"bluebird": "3.5.1",
|
||||||
"browserify": "13.3.0",
|
"browserify": "13.3.0",
|
||||||
@ -2596,15 +2604,16 @@
|
|||||||
"faye-websocket": "0.11.1",
|
"faye-websocket": "0.11.1",
|
||||||
"fuse.js": "2.6.1",
|
"fuse.js": "2.6.1",
|
||||||
"highlight.js": "9.12.0",
|
"highlight.js": "9.12.0",
|
||||||
|
"keytar": "3.0.2",
|
||||||
"lzma": "2.3.2",
|
"lzma": "2.3.2",
|
||||||
"marked": "0.3.9",
|
"marked": "0.3.12",
|
||||||
"node-hid": "0.5.7",
|
"node-hid": "0.5.7",
|
||||||
"postcss": "6.0.15",
|
"postcss": "6.0.16",
|
||||||
"request": "2.83.0",
|
"request": "2.83.0",
|
||||||
"rimraf": "2.5.4",
|
"rimraf": "2.5.4",
|
||||||
"rtlcss": "2.2.1",
|
"rtlcss": "2.2.1",
|
||||||
"serialport": "4.0.7",
|
"serialport": "4.0.7",
|
||||||
"uglify-js": "3.3.4"
|
"uglify-js": "3.3.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
@ -2641,9 +2650,9 @@
|
|||||||
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
|
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "6.0.15",
|
"version": "6.0.16",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz",
|
||||||
"integrity": "sha512-v/SpyMzLbtkmh45zUdaqLAaqXqzPdSrw8p4cQVO0/w6YiYfpj4k+Wkzhn68qk9br+H+0qfddhdPEVnbmBPfXVQ==",
|
"integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "2.3.0",
|
"chalk": "2.3.0",
|
||||||
"source-map": "0.6.1",
|
"source-map": "0.6.1",
|
||||||
@ -2695,9 +2704,9 @@
|
|||||||
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
|
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
|
||||||
},
|
},
|
||||||
"randombytes": {
|
"randombytes": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
|
||||||
"integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
|
"integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
}
|
}
|
||||||
@ -2707,14 +2716,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
|
||||||
"integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
|
"integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"randombytes": "2.0.5",
|
"randombytes": "2.0.6",
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc": {
|
"rc": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.3.tgz",
|
||||||
"integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=",
|
"integrity": "sha1-UVdakA+N1oOBxxC0cSwhVMPiA1s=",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"deep-extend": "0.4.2",
|
"deep-extend": "0.4.2",
|
||||||
@ -4310,7 +4319,7 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bl": "1.2.1",
|
"bl": "1.2.1",
|
||||||
"end-of-stream": "1.4.0",
|
"end-of-stream": "1.4.1",
|
||||||
"readable-stream": "2.3.3",
|
"readable-stream": "2.3.3",
|
||||||
"xtend": "4.0.1"
|
"xtend": "4.0.1"
|
||||||
}
|
}
|
||||||
@ -4422,9 +4431,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"uglify-js": {
|
"uglify-js": {
|
||||||
"version": "3.3.4",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.5.tgz",
|
||||||
"integrity": "sha512-hfIwuAQI5dlXP30UtdmWoYF9k+ypVqBXIdmd6ZKBiaNHHvA8ty7ZloMe3+7S5AEKVkxHbjByl4DfRHQ7QpZquw==",
|
"integrity": "sha512-ZebM2kgBL/UI9rKeAbsS2J0UPPv7SBy5hJNZml/YxB1zC6JK8IztcPs+cxilE4pu0li6vadVSFqiO7xFTKuSrg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"commander": "2.12.2",
|
"commander": "2.12.2",
|
||||||
"source-map": "0.6.1"
|
"source-map": "0.6.1"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-ev3",
|
"name": "pxt-ev3",
|
||||||
"version": "0.0.57",
|
"version": "0.0.68",
|
||||||
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
|
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
|
||||||
"private": true,
|
"private": true,
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@ -44,8 +44,8 @@
|
|||||||
"webfonts-generator": "^0.4.0"
|
"webfonts-generator": "^0.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pxt-common-packages": "0.15.4",
|
"pxt-common-packages": "0.15.6",
|
||||||
"pxt-core": "3.0.5"
|
"pxt-core": "3.0.11"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node node_modules/pxt-core/built/pxt.js travis"
|
"test": "node node_modules/pxt-core/built/pxt.js travis"
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
"libs/infrared-sensor",
|
"libs/infrared-sensor",
|
||||||
"libs/gyro-sensor",
|
"libs/gyro-sensor",
|
||||||
"libs/chassis",
|
"libs/chassis",
|
||||||
|
"libs/mood",
|
||||||
"libs/ev3",
|
"libs/ev3",
|
||||||
|
"libs/storage",
|
||||||
|
"libs/datalog",
|
||||||
"libs/tests",
|
"libs/tests",
|
||||||
"libs/behaviors"
|
"libs/behaviors"
|
||||||
],
|
],
|
||||||
|
@ -97,28 +97,21 @@ namespace pxsim {
|
|||||||
return this.brickNode;
|
return this.brickNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
motorUsed(port: number, large: boolean) {
|
motorUsed(ports: number, large: boolean): boolean {
|
||||||
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
||||||
const p = 1 << i;
|
const p = 1 << i;
|
||||||
if (port & p) {
|
if (ports & p) {
|
||||||
const motorPort = this.motorMap[p];
|
|
||||||
if (!this.outputNodes[motorPort])
|
|
||||||
this.outputNodes[motorPort] = new MotorNode(motorPort, large);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hasMotor(port: number) {
|
|
||||||
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
|
||||||
const p = 1 << i;
|
|
||||||
if (port & p) {
|
|
||||||
const motorPort = this.motorMap[p];
|
const motorPort = this.motorMap[p];
|
||||||
const outputNode = this.outputNodes[motorPort];
|
const outputNode = this.outputNodes[motorPort];
|
||||||
if (outputNode)
|
if (!outputNode) {
|
||||||
return true;
|
this.outputNodes[motorPort] = new MotorNode(motorPort, large);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (outputNode && outputNode.isLarge() != large)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMotor(port: number, large?: boolean): MotorNode[] {
|
getMotor(port: number, large?: boolean): MotorNode[] {
|
||||||
|
@ -30,8 +30,8 @@ namespace pxsim {
|
|||||||
data,
|
data,
|
||||||
beforeMemRead: () => {
|
beforeMemRead: () => {
|
||||||
//console.log("analog before read");
|
//console.log("analog before read");
|
||||||
data[AnalogOff.BatteryTemp] = 21; // TODO simulate this
|
util.map16Bit(data, AnalogOff.BatteryTemp, 21);
|
||||||
data[AnalogOff.BatteryCurrent] = 100; // TODO simulate this
|
util.map16Bit(data, AnalogOff.BatteryCurrent, 900);
|
||||||
const inputNodes = ev3board().getInputNodes();
|
const inputNodes = ev3board().getInputNodes();
|
||||||
for (let port = 0; port < DAL.NUM_INPUTS; port++) {
|
for (let port = 0; port < DAL.NUM_INPUTS; port++) {
|
||||||
const node = inputNodes[port];
|
const node = inputNodes[port];
|
||||||
|
@ -8,6 +8,7 @@ namespace pxsim.MMapMethods {
|
|||||||
read?: (d: Buffer) => number;
|
read?: (d: Buffer) => number;
|
||||||
write?: (d: Buffer) => number;
|
write?: (d: Buffer) => number;
|
||||||
ioctl?: (id: number, d: Buffer) => number;
|
ioctl?: (id: number, d: Buffer) => number;
|
||||||
|
lseek?: (offset: number, whence: number) => number;
|
||||||
}
|
}
|
||||||
|
|
||||||
import BM = pxsim.BufferMethods
|
import BM = pxsim.BufferMethods
|
||||||
@ -23,6 +24,7 @@ namespace pxsim.MMapMethods {
|
|||||||
if (!impl.read) impl.read = () => 0
|
if (!impl.read) impl.read = () => 0
|
||||||
if (!impl.write) impl.write = () => 0
|
if (!impl.write) impl.write = () => 0
|
||||||
if (!impl.ioctl) impl.ioctl = () => -1
|
if (!impl.ioctl) impl.ioctl = () => -1
|
||||||
|
if (!impl.lseek) impl.lseek = (offset, whence) => -1
|
||||||
}
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
}
|
}
|
||||||
@ -68,6 +70,10 @@ namespace pxsim.MMapMethods {
|
|||||||
export function read(m: MMap, data: Buffer): number {
|
export function read(m: MMap, data: Buffer): number {
|
||||||
return m.impl.read(data)
|
return m.impl.read(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function lseek(m: MMap, offset: number, whence: number): number {
|
||||||
|
return m.impl.lseek(offset, whence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace pxsim.control {
|
namespace pxsim.control {
|
||||||
|
@ -3,15 +3,23 @@
|
|||||||
import lf = pxsim.localization.lf;
|
import lf = pxsim.localization.lf;
|
||||||
|
|
||||||
namespace pxsim.motors {
|
namespace pxsim.motors {
|
||||||
|
function portsToString(out: number): string {
|
||||||
export function __motorUsed(port: number, large: boolean) {
|
let r = "";
|
||||||
//console.log("MOTOR INIT " + port);
|
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
||||||
if (!ev3board().hasMotor(port)) {
|
if (out & (1 << i)) {
|
||||||
ev3board().motorUsed(port, large);
|
if (r.length > 0) r += "+";
|
||||||
runtime.queueDisplayUpdate();
|
r += "ABCD"[i];
|
||||||
} else {
|
}
|
||||||
U.userError(`${lf("Multiple motors are connected to Port")} ${String.fromCharCode('A'.charCodeAt(0) + ev3board().motorMap[port])}`);
|
|
||||||
}
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __motorUsed(ports: number, large: boolean) {
|
||||||
|
//console.log("MOTOR INIT " + port);
|
||||||
|
if (ev3board().motorUsed(ports, large))
|
||||||
|
runtime.queueDisplayUpdate();
|
||||||
|
else
|
||||||
|
U.userError(`${lf("Multiple motors are connected to Port")} ${portsToString(ports)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ namespace pxsim {
|
|||||||
private speedCmdTime: number;
|
private speedCmdTime: number;
|
||||||
private _synchedMotor: MotorNode; // non-null if synchronized
|
private _synchedMotor: MotorNode; // non-null if synchronized
|
||||||
|
|
||||||
|
private manualSpeed: number = undefined;
|
||||||
|
|
||||||
constructor(port: number, large: boolean) {
|
constructor(port: number, large: boolean) {
|
||||||
super(port);
|
super(port);
|
||||||
this.setLarge(large);
|
this.setLarge(large);
|
||||||
@ -40,6 +42,10 @@ namespace pxsim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setSpeedCmd(cmd: DAL, values: number[]) {
|
setSpeedCmd(cmd: DAL, values: number[]) {
|
||||||
|
if (this.speedCmd != cmd ||
|
||||||
|
JSON.stringify(this.speedCmdValues) != JSON.stringify(values))
|
||||||
|
this.setChangedState();
|
||||||
|
// new command TODO: values
|
||||||
this.speedCmd = cmd;
|
this.speedCmd = cmd;
|
||||||
this.speedCmdValues = values;
|
this.speedCmdValues = values;
|
||||||
this.speedCmdTacho = this.angle;
|
this.speedCmdTacho = this.angle;
|
||||||
@ -64,6 +70,10 @@ namespace pxsim {
|
|||||||
this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000;
|
this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLarge(): boolean {
|
||||||
|
return this.id == NodeType.LargeMotor;
|
||||||
|
}
|
||||||
|
|
||||||
setPolarity(polarity: number) {
|
setPolarity(polarity: number) {
|
||||||
// Either 1 or 255 (reverse)
|
// Either 1 or 255 (reverse)
|
||||||
/*
|
/*
|
||||||
@ -92,6 +102,17 @@ namespace pxsim {
|
|||||||
this.started = true;
|
this.started = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
manualMotorDown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
manualMotorMove(speed: number) {
|
||||||
|
this.manualSpeed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
manualMotorUp() {
|
||||||
|
this.manualSpeed = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
updateState(elapsed: number) {
|
updateState(elapsed: number) {
|
||||||
//console.log(`motor: ${elapsed}ms - ${this.speed}% - ${this.angle}> - ${this.tacho}|`)
|
//console.log(`motor: ${elapsed}ms - ${this.speed}% - ${this.angle}> - ${this.tacho}|`)
|
||||||
const interval = Math.min(20, elapsed);
|
const interval = Math.min(20, elapsed);
|
||||||
@ -105,79 +126,84 @@ namespace pxsim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateStateStep(elapsed: number) {
|
private updateStateStep(elapsed: number) {
|
||||||
// compute new speed
|
if (!this.manualSpeed) {
|
||||||
switch (this.speedCmd) {
|
// compute new speed
|
||||||
case DAL.opOutputSpeed:
|
switch (this.speedCmd) {
|
||||||
case DAL.opOutputPower:
|
case DAL.opOutputSpeed:
|
||||||
// assume power == speed
|
case DAL.opOutputPower:
|
||||||
// TODO: PID
|
// assume power == speed
|
||||||
this.speed = this.speedCmdValues[0];
|
// TODO: PID
|
||||||
break;
|
this.speed = this.speedCmdValues[0];
|
||||||
case DAL.opOutputTimeSpeed:
|
break;
|
||||||
case DAL.opOutputTimePower:
|
case DAL.opOutputTimeSpeed:
|
||||||
case DAL.opOutputStepPower:
|
case DAL.opOutputTimePower:
|
||||||
case DAL.opOutputStepSpeed: {
|
case DAL.opOutputStepPower:
|
||||||
// ramp up, run, ramp down, <brake> using time
|
case DAL.opOutputStepSpeed: {
|
||||||
const speed = this.speedCmdValues[0];
|
// ramp up, run, ramp down, <brake> using time
|
||||||
const step1 = this.speedCmdValues[1];
|
const speed = this.speedCmdValues[0];
|
||||||
const step2 = this.speedCmdValues[2];
|
const step1 = this.speedCmdValues[1];
|
||||||
const step3 = this.speedCmdValues[3];
|
const step2 = this.speedCmdValues[2];
|
||||||
const brake = this.speedCmdValues[4];
|
const step3 = this.speedCmdValues[3];
|
||||||
const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed)
|
const brake = this.speedCmdValues[4];
|
||||||
? pxsim.U.now() - this.speedCmdTime
|
const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed)
|
||||||
: this.tacho - this.speedCmdTacho;
|
? pxsim.U.now() - this.speedCmdTime
|
||||||
if (dstep < step1) // rampup
|
: this.tacho - this.speedCmdTacho;
|
||||||
this.speed = speed * dstep / step1;
|
if (dstep < step1) // rampup
|
||||||
else if (dstep < step1 + step2) // run
|
this.speed = speed * dstep / step1;
|
||||||
this.speed = speed;
|
else if (dstep < step1 + step2) // run
|
||||||
else if (dstep < step1 + step2 + step3)
|
this.speed = speed;
|
||||||
this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3);
|
else if (dstep < step1 + step2 + step3)
|
||||||
else {
|
this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3);
|
||||||
if (brake) this.speed = 0;
|
else {
|
||||||
this.clearSpeedCmd();
|
if (brake) this.speed = 0;
|
||||||
}
|
this.clearSpeedCmd();
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
case DAL.opOutputStepSync:
|
|
||||||
case DAL.opOutputTimeSync: {
|
|
||||||
const otherMotor = this._synchedMotor;
|
|
||||||
if (otherMotor.port < this.port) // handled in other motor code
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const speed = this.speedCmdValues[0];
|
|
||||||
const turnRatio = this.speedCmdValues[1];
|
|
||||||
const stepsOrTime = this.speedCmdValues[2];
|
|
||||||
const brake = this.speedCmdValues[3];
|
|
||||||
const dstep = this.speedCmd == DAL.opOutputTimeSync
|
|
||||||
? pxsim.U.now() - this.speedCmdTime
|
|
||||||
: this.tacho - this.speedCmdTacho;
|
|
||||||
// 0 is special case, run infinite
|
|
||||||
if (!stepsOrTime || dstep < stepsOrTime)
|
|
||||||
this.speed = speed;
|
|
||||||
else {
|
|
||||||
if (brake) this.speed = 0;
|
|
||||||
this.clearSpeedCmd();
|
|
||||||
}
|
}
|
||||||
|
case DAL.opOutputStepSync:
|
||||||
|
case DAL.opOutputTimeSync: {
|
||||||
|
const otherMotor = this._synchedMotor;
|
||||||
|
if (otherMotor.port < this.port) // handled in other motor code
|
||||||
|
break;
|
||||||
|
|
||||||
// turn ratio is a bit weird to interpret
|
const speed = this.speedCmdValues[0];
|
||||||
// see https://communities.theiet.org/blogs/698/1706
|
const turnRatio = this.speedCmdValues[1];
|
||||||
if (turnRatio < 0) {
|
const stepsOrTime = this.speedCmdValues[2];
|
||||||
otherMotor.speed = speed;
|
const brake = this.speedCmdValues[3];
|
||||||
this.speed *= (100 + turnRatio) / 100;
|
const dstep = this.speedCmd == DAL.opOutputTimeSync
|
||||||
} else {
|
? pxsim.U.now() - this.speedCmdTime
|
||||||
otherMotor.speed = this.speed * (100 - turnRatio) / 100;
|
: this.tacho - this.speedCmdTacho;
|
||||||
|
// 0 is special case, run infinite
|
||||||
|
if (!stepsOrTime || dstep < stepsOrTime)
|
||||||
|
this.speed = speed;
|
||||||
|
else {
|
||||||
|
if (brake) this.speed = 0;
|
||||||
|
this.clearSpeedCmd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// turn ratio is a bit weird to interpret
|
||||||
|
// see https://communities.theiet.org/blogs/698/1706
|
||||||
|
if (turnRatio < 0) {
|
||||||
|
otherMotor.speed = speed;
|
||||||
|
this.speed *= (100 + turnRatio) / 100;
|
||||||
|
} else {
|
||||||
|
otherMotor.speed = this.speed * (100 - turnRatio) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clamp
|
||||||
|
this.speed = Math.max(-100, Math.min(100, this.speed >> 0));
|
||||||
|
otherMotor.speed = Math.max(-100, Math.min(100, otherMotor.speed >> 0));;
|
||||||
|
|
||||||
|
// stop other motor if needed
|
||||||
|
if (!this._synchedMotor)
|
||||||
|
otherMotor.clearSpeedCmd();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clamp
|
|
||||||
this.speed = Math.max(-100, Math.min(100, this.speed >> 0));
|
|
||||||
otherMotor.speed = Math.max(-100, Math.min(100, otherMotor.speed >> 0));;
|
|
||||||
|
|
||||||
// stop other motor if needed
|
|
||||||
if (!this._synchedMotor)
|
|
||||||
otherMotor.clearSpeedCmd();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.speed = this.manualSpeed;
|
||||||
|
}
|
||||||
this.speed = Math.round(this.speed); // integer only
|
this.speed = Math.round(this.speed); // integer only
|
||||||
|
|
||||||
// compute delta angle
|
// compute delta angle
|
||||||
|
@ -97,6 +97,7 @@ namespace pxsim {
|
|||||||
motors.forEach(motor => motor.stop());
|
motors.forEach(motor => motor.stop());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
case DAL.opOutputPower:
|
||||||
case DAL.opOutputSpeed: {
|
case DAL.opOutputSpeed: {
|
||||||
// setSpeed
|
// setSpeed
|
||||||
const port = buf.data[1];
|
const port = buf.data[1];
|
||||||
|
23
sim/state/storage.ts
Normal file
23
sim/state/storage.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
namespace pxsim.storage {
|
||||||
|
export function __stringToBuffer(s: string): RefBuffer {
|
||||||
|
// TODO
|
||||||
|
return new RefBuffer(new Uint8Array([]));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __bufferToString(b: RefBuffer): string {
|
||||||
|
// TODO
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __mkdir(fn: string) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __unlink(filename: string): void {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __truncate(filename: string): void {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
@ -1,92 +1,77 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 82 156">
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<defs>
|
<svg width="82px" height="156px" viewBox="0 0 82 156" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<clipPath id="clip-path" transform="translate(0.98 1.9)">
|
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
|
||||||
<path d="M79,17.05A17.07,17.07,0,0,1,64.92,33.86l.36.39V70c0,.42-.14.4-.39.68L54,81.22v10l.75.78v.79h6.79a4,4,0,0,1,4,4v25.82a4,4,0,0,1-4,4H54.75v8.18A5.79,5.79,0,0,1,49,140.61h-6.5v7.57a4,4,0,0,1-2.9,3.84v1a.6.6,0,0,1-.6.6H12.69a.6.6,0,0,1-.6-.6h0v-1.29a4,4,0,0,1-2.17-3.55v-7.57H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59l13.68.1,0-11.8H26a4,4,0,0,1-4-4V39.79a4,4,0,0,1,4-4h6.78l0-11.77c0-.84.15-.84.46-1.14l10.41-10.1.22-.19a1.53,1.53,0,0,1,1.59.23A17.07,17.07,0,0,1,79,17.05Z" style="fill: none"/>
|
<title>Large Motor</title>
|
||||||
</clipPath>
|
<desc>Created with Sketch.</desc>
|
||||||
<clipPath id="clip-path-2" transform="translate(0.98 1.9)">
|
<defs></defs>
|
||||||
<path d="M49,140.61H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59s19.46.14,23.87.14a2.27,2.27,0,0,1,2.37,1L54.75,92v42.79A5.79,5.79,0,0,1,49,140.61Z" style="fill: none"/>
|
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-66.000000, -54.000000)">
|
||||||
</clipPath>
|
<g id="Large-Motor" transform="translate(66.000000, 54.000000)">
|
||||||
<clipPath id="clip-path-3" transform="translate(0.98 1.9)">
|
<path d="M39.98,155.52 L13.67,155.52 C13.3386292,155.52 13.07,155.251371 13.07,154.92 L13.07,149.62 C13.07,149.288629 13.3386292,149.02 13.67,149.02 L39.98,149.02 C40.3113708,149.02 40.58,149.288629 40.58,149.62 L40.58,154.9 C40.5854219,155.062566 40.5246096,155.220368 40.4114947,155.337253 C40.2983799,155.454138 40.1426565,155.52009 39.98,155.52 Z" id="LM_back2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path d="M43.18,135.24H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.21C15,95.94,21.86,86.8,21.86,86.8H43.18A5.78,5.78,0,0,1,49,92.58h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" style="fill: none"/>
|
<g id="Group" transform="translate(9.000000, 136.000000)">
|
||||||
</clipPath>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAAAXNSR0IArs4c6QAAAMRJREFUSA3tlrERwjAMRW2OEmYgPQMwFrMwAytBT1iB9OY/x05J1IAopLtv2Y5yevfPhXIpJWVF+oMQSwEDmJ00tKzkFpM6P8Q1bbUZpLN0lLwcw6G7dJFuQOEUQCfJE0rtK0sCigCmq144LIshG4fmqy0DatWiVhBOhVNWB6x18abCKasD1rr+puocY/3pS3ULA1DMMU/pJfHBQ/SGAZY6JYzKVw6Kw5x+vnYGcsptHN5rDxCzlUfg0CgWHJuhPCg+9XwDDy9ID0K8XgsAAAAASUVORK5CYII="></image>
|
||||||
</defs>
|
<path d="M33.84,18.07 L2.51,18.07 C2.17862915,18.07 1.91,17.8013708 1.91,17.47 L1.91,2.77 C1.91,2.43862915 2.17862915,2.17 2.51,2.17 L33.84,2.17 C34.1713708,2.17 34.44,2.43862915 34.44,2.77 L34.44,17.47 C34.44,17.8013708 34.1713708,18.07 33.84,18.07 Z" id="LM_back1-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<title>Large Motor</title>
|
</g>
|
||||||
<g style="isolation: isolate">
|
<g id="LM_rightside" transform="translate(22.000000, 37.000000)" fill-rule="nonzero">
|
||||||
<g id="e13b39e7-895d-4931-9be9-7aecaf709784">
|
<path d="M12.06,34.51 L6.45,34.51 C4.99937339,34.5153259 3.60647912,33.9421088 2.57978624,32.9172929 C1.55309337,31.892477 0.977328505,30.5006339 0.98,29.05 L0.98,6.15 C0.977339027,4.70110385 1.55173283,3.31078487 2.57625885,2.28625885 C3.60078487,1.26173283 4.99110385,0.687339027 6.44,0.69 L12.05,0.69 C15.0654747,0.69 17.51,3.13452527 17.51,6.15 L17.51,29.05 C17.5126553,30.4971617 16.939633,31.8859609 15.9172718,32.910198 C14.8949106,33.9344351 13.5071641,34.5100024 12.06,34.51 Z" id="LM_rightside5" fill="#A8AAA8"></path>
|
||||||
<g style="clip-path: url(#clip-path)">
|
<circle id="LM_rightside4" fill="#FFFFFF" cx="6.3" cy="29.21" r="3.79"></circle>
|
||||||
<g id="Large_Motor" data-name="Large Motor">
|
<circle id="LM_rightside3" fill="#FFFFFF" cx="6.3" cy="6" r="3.79"></circle>
|
||||||
<path id="LM_back2" data-name="LM back2" d="M39,153.62H12.69a.6.6,0,0,1-.6-.6h0v-5.3a.6.6,0,0,1,.6-.6H39a.6.6,0,0,1,.6.6V153A.6.6,0,0,1,39,153.62Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<path d="M3.38,24.59 C4.07351535,24.1313154 4.88857129,23.8909784 5.72,23.9 C6.76862292,23.8298668 7.81405119,24.0772848 8.72,24.61 C9.97,25.54 9.95,24.51 9.95,24.51 L9.95,22.71 C9.95,22.26 9.39,21.86 8.72,22.25 L7.72,22.83 C7.72,22.83 7.36,23.02 7.36,22.5 L7.36,19.9 C7.36,19.9 7.36,19.11 8.09,19.13 C8.82,19.15 9.47,19.13 9.47,19.13 C9.47,19.13 9.76,18.88 9.76,17.74 C9.76,16.6 9.47,16.42 9.47,16.42 L8.08,16.42 C8.08,16.42 7.35,16.42 7.35,15.77 L7.35,14.47 C7.35,14.47 7.12,14.11 6.18,14.17 C5.6978322,14.1741563 5.22153417,14.2762201 4.78,14.47 L4.78,15.77 C4.77453579,16.1305967 4.48063814,16.4200414 4.12,16.42 C3.49,16.42 2.86,16.42 2.86,16.42 C2.86,16.42 2.61,16.61 2.57,17.74 C2.53,18.87 2.86,19.13 2.86,19.13 L4.12,19.13 C4.12,19.13 4.92,19.18 4.94,19.9 C4.96,20.62 4.94,22.52 4.94,22.52 C4.94,22.52 4.94,23.03 4.6,22.85 L3.39,22.27 C3.39,22.27 2.56,21.86 2.57,22.73 C2.58,23.6 2.57,24.53 2.57,24.53 C2.57,24.53 2.65,25.02 3.38,24.59 Z" id="LM_rightside2" fill="#FFFFFF"></path>
|
||||||
<g>
|
<path d="M10.23,12.79 C10.1913976,13.0147775 10.0630557,13.2141964 9.87446015,13.3424414 C9.68586455,13.4706864 9.453229,13.5167322 9.23,13.47 C9.14591061,13.4523039 9.06499079,13.421959 8.99,13.38 C8.1099436,12.9124008 7.1357966,12.6492102 6.14,12.61 C5.162003,12.5962776 4.20061308,12.8635231 3.37,13.38 C2.54,13.78 2.3,12.79 2.3,12.79 L2.3,11.03 C2.33192589,10.6400455 2.66941985,10.3469587 3.06,10.37 C3.16998614,10.3773249 3.27646607,10.4116733 3.37,10.47 C4.20732336,10.980005 5.16044012,11.2690368 6.14,11.31 C7.13850164,11.2335413 8.10964397,10.9473099 8.99,10.47 C8.99,10.47 10.17,10.23 10.19,11.03 C10.21,11.83 10.23,12.79 10.23,12.79 Z" id="LM_rightside1" fill="#FFFFFF"></path>
|
||||||
<image width="36" height="20" transform="translate(9 136)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAACXBIWXMAAAsSAAALEgHS3X78AAAAp0lEQVRIS+3WsW3DMBBG4Y+GSmcGp/cAHsuzeIasFPdWVpD6c0FKcBWwOxV8wIEgSIAPvOL+EhFKKcUBiIiAgjO+25rJildErJMqdMdVlcwg8MQDv5P6Q1fc5ErRujW1TfmoLPa3T//dymJI9TKkehlSvQypXoZUL5vUNhAz2R1Oao75w9IOMmpRHVZqSpjxo3KRw+YwQ2lx+EsVykqfK+aIWGhSR+MNDy9ID5XUCOsAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
</g>
|
||||||
<path id="LM_back1-2" data-name="LM back1-2" d="M41.86,152.17H10.53a.6.6,0,0,1-.6-.6v-14.7a.6.6,0,0,1,.6-.6H41.86a.6.6,0,0,1,.6.6h0v14.7A.6.6,0,0,1,41.86,152.17Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<g id="Group" transform="translate(32.000000, 12.000000)">
|
||||||
</g>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="76" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAAAXNSR0IArs4c6QAAAnlJREFUaAXtmsFRwzAQRROGI6EEwhmGEqABTtyhACqiAC4cOVBBaAEKCB0AuYf/hdbjBMcrbYTlw+7MZp3IWr98OZIn2ul6vZ7k2BTG89Evr2PGRaY5ucEzQ+55zL9EXP0HXDJUBLoCyG2EekZ8hy8B9h0/KxKSoFpA97jqJZxDSKUI9QhflAQ7RMJe2wKiUhxC2jn8BH7ENzivGFgvVA9Q4MDLMZygwUqB7YRSgISDkcoVBeuEygASuLJgnBLaHr/5NeIL/AvO+SjVP3HuE/wCHn5E7dypxwfo3JhBoaZvPKBiZ9F5bDOhR28msSrUVpLqUmXmmkn+nBiGjp1jEsuQtYHkeC8wsBQH2huMv745/A7Omdp+H6DzljGXaaogFGdkzswlgZAumAlM5qnwOCKZCsdsMIEqzPEnXRbYUFCkTAYbEioZbGioJLAaUCpYLahesJpQO8FqQwkYV5MVnM/9bxuPLjyjknG64KoSnvfHAkUtmlVlTFAEC+ZQooQWXSlNIWl3pUQJLbpSmkLS7kqJElp0pTSFpN2VEiW06EppCkm7KyVKaNGV0hSSdldKlNCiK6UpJO2ulCihRVdKU0jaXSlRQouulKaQtI9JKW7JBRsLFCtAPuD8M3YyBigCvcJZCcJ/h6tDEWgBf2DEPnOomampVCcQ4KoptROoFlQvUA0oFWhoqCSgIaGSgYaCygIaAiobiFCy3yelIPyM1uwo/b41vZqAeCVCcb1hwR+NMNxzY6lJ2HtDtBiBuHRszNSpiQTiFB0EgkA3cEarcQ0zVzWGajAUc7WHq4RSYetV1rLcb9ZZ57kFmZsznA8g3qcm64QyZSrY6Qey39wRVmjftAAAAABJRU5ErkJggg=="></image>
|
||||||
<g id="LM_rightside" data-name="LM rightside">
|
<path d="M33.89,60.6 L20.48,73.53 L1.91,72.9 L1.74,13.9 C1.74,13.06 1.9,13.06 2.2,12.77 L12.62,2.67 L12.83,2.48 C13.42,2.08 14.83,2.59 14.83,3.43 L34.27,24.15 L34.27,59.9 C34.28,60.34 34.14,60.33 33.89,60.6 Z" id="LM_level4-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path id="LM_rightside5" data-name="LM rightside5" d="M33.08,69.61H27.47A5.45,5.45,0,0,1,22,64.15h0V41.25a5.45,5.45,0,0,1,5.46-5.46h5.61a5.46,5.46,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,33.08,69.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
</g>
|
||||||
<circle id="LM_rightside4" data-name="LM rightside4" cx="28.3" cy="66.21" r="3.79" style="fill: #fff"/>
|
<g id="Group" transform="translate(32.000000, 69.000000)">
|
||||||
<circle id="LM_rightside3" data-name="LM rightside3" cx="28.3" cy="43" r="3.79" style="fill: #fff"/>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="25" height="27" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAAAXNSR0IArs4c6QAAAZhJREFUSA3tlj1SwzAQRnEmJanogYoChiOQC1BxAA7AcTgDDQfgBLlDekxNQ5LefE/WeizHGa9l07Ezny3L2n36W9lFVVVnXStk3Trvs+IdB5Rz0a0XY6X6K+ncG7zV7qByqZj7Vl0oJqAIWevNswRsrJVyeJM2XdjSIrUgL6p7kBjZWLuVQ5gJxUthcepYk3vpXfqRmOdc7eT7IT1KK+IjGxG9pzcoZyRyawx/ZiSsl0a2FahaxCnjBetyLWXvOPmaAbuUmg210AOLDgTY1NEoRGNJhwFBhT4npKFZARCW0Ouqea8GmjdqT7R/UM+k+KosYe0U8HhlbRxAZPA2EoaCkArkHfehtjFkfQP0Kb1KTRarfMqAPEl3EmV37i11DB04j+TkMdohQJwmfFJcsLBGHHpy8Ng+dupLjZlyzAWzzVC7OK6xUzsBN63mg7DRIAsuIKNzw7JBAMfAJoFOwPjcHO3gyaAeGJuEL3XyJzQLqAMrI+imDUt+t3CYatognBhM3YX0rXUMaTA7yDoKMKZCqPozkAHt/gsh4I9CsIZ80gAAAABJRU5ErkJggg=="></image>
|
||||||
<path id="LM_rightside2" data-name="LM rightside2" d="M24.4,59.69A4.16,4.16,0,0,1,26.74,59a5.23,5.23,0,0,1,3,.71c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.85-1.23-.46l-1,.58s-.36.19-.36-.33V55s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.39-.29-1.32-.29-1.32H29.1s-.73,0-.73-.65v-1.3s-.23-.36-1.17-.3a3.56,3.56,0,0,0-1.4.3v1.3a.66.66,0,0,1-.66.65c-.63,0-1.26,0-1.26,0s-.25.19-.29,1.32.29,1.39.29,1.39h1.26s.8.05.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.41-.82.46,0,1.8,0,1.8S23.67,60.12,24.4,59.69Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
<path d="M22.9800421,24.9 L22.98,7.6 C22.9824406,7.20649401 22.8788083,6.81960003 22.68,6.48 C22.4,6.21 19.16,2.86 19.16,2.86 C18.8448174,2.57277854 18.4252272,2.42809227 18,2.46 C17.25,2.46 6.38,2.46 6.38,2.46 L1.98,7.16 L1.98,15.16 L12.64,15.73 L22.9800421,24.9 Z" id="LM_level3-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path id="LM_rightside1" data-name="LM rightside1" d="M31.25,47.89a.84.84,0,0,1-1,.68.85.85,0,0,1-.24-.09,6.63,6.63,0,0,0-2.85-.77,5.11,5.11,0,0,0-2.77.77c-.83.4-1.07-.59-1.07-.59V46.13a.72.72,0,0,1,.76-.66.67.67,0,0,1,.31.1,5.79,5.79,0,0,0,2.77.84,7.12,7.12,0,0,0,2.85-.84s1.18-.24,1.2.56S31.25,47.89,31.25,47.89Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
</g>
|
||||||
</g>
|
<g id="LM_leftside" transform="translate(49.000000, 94.000000)" fill-rule="nonzero">
|
||||||
<g>
|
<path d="M12.06,34.54 L6.45,34.54 C4.99937339,34.5453259 3.60647912,33.9721088 2.57978624,32.9472929 C1.55309337,31.922477 0.977328505,30.5306339 0.98,29.08 L0.98,6.18 C0.98,3.16452527 3.42452527,0.72 6.44,0.72 L12.05,0.72 C15.0631921,0.725503561 17.5044964,3.16680786 17.51,6.18 L17.51,29.08 C17.5126553,30.5271617 16.939633,31.9159609 15.9172718,32.940198 C14.8949106,33.9644351 13.5071641,34.5400024 12.06,34.54 Z" id="LM_leftside5" fill="#A8AAA8"></path>
|
||||||
<image width="36" height="76" transform="translate(32 12)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAACXBIWXMAAAsSAAALEgHS3X78AAACAElEQVRoQ+3avVHDMBiA4VdcypgREmo4RggLpKKHAZiIAWgoKZggrEAGCBsQpxeFpNgJ/vkkK5YLvXe6g2Cb53zE9oVPaa3xSSmlALTvjh4pn2MrpQpgab/dAYdL4MQoC3oAnuxLH8AW2Gmty9YdAxKhaqAXYAUozJnaAm/AJiZs1rfBGegBKOyP7oAFMLfbRYN1ojpAYM7WtX3dbR8F1orqAdVz27n9BsMaUR4gV1yY1vpkYX7BGvgE9oD2WL/AO3CPfROFrKs6MOAMnVcAt3b57lsV6QzV194eYw0UfWelacUGRYFdAjQYNsPcy54xV+rwv4P/Bb8jZ5gr8oK4IFcQzF2nVOdWw/KG9d77IuUFGwsFHrAxUSCEjY0CASwFCnpgqVDQAUuJghZYahQY2Ao4YJ77v08eXRJWUHvenwoKaneVKaGOZZS0jJKWUdIySlpGScsoaRklLaOkZZS0jJKWUdIySlpGScsoaRklLaOkTQml3RdTQZXAD+bD2EmgSuALMwmyg/SoEtgAr9RGU1KiGkGQDtUKgjSoThCMj+oFwbgoEQjGQ4lBMA7KCwSXR3mDoPonpBsFccWYUwgCgUEdMAN/YDBzzKjJvG0nQe7W4Q2CCnFDhVgCj1TznCHtGDDVqLTWxylXW4wzdWDA/GfjnOcZMijddGBhouHTsfsDst/cEY24RzwAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
<circle id="LM_leftside4" fill="#FFFFFF" cx="12.67" cy="29.24" r="3.79"></circle>
|
||||||
<path id="LM_level4-2" data-name="LM level4-2" d="M64.91,70.7,51.5,83.63,32.93,83,32.76,24c0-.84.16-.84.46-1.13l10.42-10.1.21-.19c.59-.4,2,.11,2,.95L65.29,34.25V70C65.3,70.44,65.16,70.43,64.91,70.7Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<circle id="LM_leftside3" fill="#FFFFFF" cx="12.67" cy="6.03" r="3.79"></circle>
|
||||||
</g>
|
<path d="M9.75,24.62 C10.4421225,24.1572205 11.2574415,23.9133217 12.09,23.92 C13.1380484,23.8411302 14.1850856,24.0854388 15.09,24.62 C16.34,25.55 16.32,24.52 16.32,24.52 L16.32,22.72 C16.32,22.27 15.76,21.88 15.09,22.26 L14.09,22.84 C14.09,22.84 13.73,23.03 13.73,22.51 L13.73,19.9 C13.73,19.9 13.73,19.11 14.46,19.13 C15.19,19.15 15.84,19.13 15.84,19.13 C15.84,19.13 16.13,18.88 16.13,17.75 C16.13,16.62 15.84,16.42 15.84,16.42 L14.45,16.42 C14.45,16.42 13.72,16.42 13.72,15.78 L13.72,14.48 C13.72,14.48 13.49,14.12 12.55,14.17 C12.0671703,14.1775857 11.5908982,14.283046 11.15,14.48 L11.15,15.78 C11.1391868,16.1366743 10.8468382,16.4201639 10.49,16.42 L9.23,16.42 C9.23,16.42 8.98,16.62 8.94,17.75 C8.9,18.88 9.23,19.13 9.23,19.13 L10.49,19.13 C10.49,19.13 11.29,19.13 11.31,19.9 C11.33,20.67 11.31,22.52 11.31,22.52 C11.31,22.52 11.31,23.03 10.97,22.85 L9.76,22.27 C9.76,22.27 8.93,21.87 8.94,22.73 C8.95,23.59 8.94,24.53 8.94,24.53 C8.94,24.53 8.98,25.06 9.75,24.62 Z" id="LM_leftside2" fill="#FFFFFF"></path>
|
||||||
<g>
|
<path d="M16.6,12.82 C16.5640845,13.0461448 16.4363396,13.2474057 16.2469908,13.3761629 C16.057642,13.5049201 15.8235128,13.5497335 15.6,13.5 C15.5157002,13.4885804 15.4342916,13.4614442 15.36,13.42 C14.4821686,12.9467916 13.506699,12.6832437 12.51,12.65 C11.5311949,12.6299456 10.5680375,12.8976825 9.74,13.42 C8.91,13.82 8.67,12.82 8.67,12.82 L8.67,11.06 C8.70188656,10.6714097 9.04116607,10.3812364 9.43,10.41 C9.53837526,10.4186243 9.6438555,10.4492476 9.74,10.5 C10.5773234,11.010005 11.5304401,11.2990368 12.51,11.34 C13.5091637,11.2671668 14.4810541,10.9807149 15.36,10.5 C15.36,10.5 16.54,10.26 16.56,11.06 C16.58,11.86 16.6,12.82 16.6,12.82 Z" id="LM_leftside1" fill="#FFFFFF"></path>
|
||||||
<image width="25" height="27" transform="translate(32 69)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAACXBIWXMAAAsSAAALEgHS3X78AAABYUlEQVRIS+2WvVXDMBRG7/NxGVf0CRVFchghWSAVA2QAxmEGGgZgguzgHlPTELv/KCSD/BMs2wkV9xwf2/LPlZ70JJkk2piZdQojUd8PAWuXm1kGrIBF3wcDVEAhqWw/aIi8ZAcccLKxFMAzcGzL0voikDwCWyBjPGt8JMysKfMtMuAeeAE+Ac04TsArsAcySUj6blGGq82aaS0JyXARqYDCzHJJSnzItrh+ucW1bi4ZsCQYUAmu0w9M75dzNCqc4KxLLivpkPjzJcL1Kwl/xL9oMnXC1lkdw6SBk+IyOPf3Qz9Z8DOzD73bIAXegCfiloUV8ABs/HV07qWSKjPLiSP3xwY3m+yIlKVwflXsofSVeseFHCJlKSPxlTqZ2TEoHpSNFtVIKsfIJotgnGyWCHplW3pG8GwRdGQVbqXu35zMJZAVONEdgayzr5uL33wugBvgQ1IFVxDVmJmF+Xk1UZsvIeCPQjWq5BoAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
</g>
|
||||||
<path id="LM_level3-2" data-name="LM level3-2" d="M54,92V74.7a2.19,2.19,0,0,0-.3-1.12c-.28-.27-3.52-3.62-3.52-3.62a1.55,1.55,0,0,0-1.16-.4c-.75,0-11.62,0-11.62,0L33,74.26v8l10.66.57Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<g id="Group" transform="translate(0.000000, 81.000000)">
|
||||||
</g>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="58" height="64" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAAAXNSR0IArs4c6QAAAqRJREFUaAXtm01OwzAQhSlUYgNbJDalaxBHgAtwBg7AiVixYsOODScoN0DqAcoNoJUQq/CecaK64zhOm7T1yCNNf+zUns/P4xjkDIqiOOjKBrCu2mpqB3G3Dnywxm+8cYDzFBUX8BPvBd0WLtDcDL5oA90JrAW9Ref3cAL3bQR9hU/hMwDPYzrcGHYJ9AEd3sCpcN9WKkvYZ/gkBni4SVQroFR2G6AMmf1cwUdwkzaIpRmYObuO2w7v8P4G/4ZzwdiFf6HfF/g13MzUOp5DXNDaMIpcdcdw5ui2pi668hpVvrQenFlrwaLh6A684XVb6Ay8TS1vD61z1jZGNanqGM7Odm0cfK4ZxhCjN39bwVpQNsqVd5sL0j9F+LUROBoWoM50Qb/B/AjH1VttEDga1sJFLQS9ocQ1XAscBWun777laQidwIzXbD4Q/xS3o6JxNbag+5qnTcAjXFDt1YOwAE0hT0PAzp0iCItWOB1SyNMQcFVXC2unb0p5WkHVffDCJpyndZymXMAqyNNaYAGLK1Xl6TK5A6sxT72wWvNUwGrOUwGLArV56sBqz1MHFl/4r0/+Ic4NBBVWa1yNuVHmhlk1KBUsbz3OhpkVGq2E1cgmmDKsGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjFJZnu3XaA4XYXly8xMe9WxMQiNCHnKRz9gRXn/gfILiDH4OP4anbgR9hz/BP3D69pdAQ3yY41zFhF+spX7coAR9BI/zrIA5XL0CTNl5ziJVmyFw71NczuNp9uQMQasDyQkSm9PjFHA1dgeWlfYA2Op1SX0HqLMKl8EL2LJC4/sftL72OnfR538AAAAASUVORK5CYII="></image>
|
||||||
<g id="LM_leftside" data-name="LM leftside">
|
<path d="M49.98,61.51 L7.29,61.51 C4.09779415,61.51 1.51,58.9222059 1.51,55.73 L1.51,26.09 C11.87,12.03 19.63,2.22 19.63,2.22 L20.23,2.22 C20.23,2.22 39.69,2.37 44.09,2.37 C45.013529,2.18179526 45.9580478,2.5786519 46.47,3.37 L55.73,12.9 L55.73,55.7 C55.7379772,57.2329575 55.1366519,58.7062958 54.0583133,59.7958867 C52.9799747,60.8854775 51.5129577,61.5020641 49.98,61.51 Z" id="LM_level2_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path id="LM_leftside5" data-name="LM leftside5" d="M60.08,126.64H54.47A5.45,5.45,0,0,1,49,121.18h0V98.28a5.46,5.46,0,0,1,5.46-5.46h5.61a5.47,5.47,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,60.08,126.64Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
</g>
|
||||||
<circle id="LM_leftside4" data-name="LM leftside4" cx="61.67" cy="123.24" r="3.79" style="fill: #fff"/>
|
<g id="LM_total">
|
||||||
<circle id="LM_leftside3" data-name="LM leftside3" cx="61.67" cy="100.03" r="3.79" style="fill: #fff"/>
|
<g id="LM_whitepart" transform="translate(0.000000, 89.000000)" fill="#F1F1F1" fill-rule="nonzero">
|
||||||
<path id="LM_leftside2" data-name="LM leftside2" d="M57.77,116.72a4.15,4.15,0,0,1,2.34-.7,5.14,5.14,0,0,1,3,.7c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.84-1.23-.46l-1,.58s-.36.19-.36-.33V112s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.38-.29-1.33-.29-1.33H62.47s-.73,0-.73-.64v-1.3s-.23-.36-1.17-.31a3.57,3.57,0,0,0-1.4.31v1.3a.66.66,0,0,1-.66.64H57.25s-.25.2-.29,1.33.29,1.38.29,1.38h1.26s.8,0,.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.4-.82.46,0,1.8,0,1.8S57,117.16,57.77,116.72Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
<g id="LM_whitepart_combined">
|
||||||
<path id="LM_leftside1" data-name="LM leftside1" d="M64.62,104.92a.83.83,0,0,1-1,.68.68.68,0,0,1-.24-.08,6.46,6.46,0,0,0-2.85-.77,5,5,0,0,0-2.77.77c-.83.4-1.07-.6-1.07-.6v-1.76a.71.71,0,0,1,.76-.65.8.8,0,0,1,.31.09,5.79,5.79,0,0,0,2.77.84,7,7,0,0,0,2.85-.84s1.18-.24,1.2.56S64.62,104.92,64.62,104.92Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
<polygon id="LM_whitepart_top" points="44.46 53.9 37.31 46.53 13.52 15.46 13.52 0.6 0.46 16.74 0.46 47.96 1.46 55.65"></polygon>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
|
||||||
<image width="58" height="64" transform="translate(0 81)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAACXBIWXMAAAsSAAALEgHS3X78AAACFElEQVRoQ+2bQY7TMBSGvxcqsaFbJDbDrEEcYeYCcwYOwIlYsWLDjg0nGG6A1ANkbgCNhGb1WNgBpxPbaUjT+smf5E3lxPlq/25S5YmqshQiIrk+S6EzLlxmHDOKiGyB18CLXN8F6IAW6I6RXkTWi94C73HCp6YFvgI7oFXVfaY/sIBsIPoBuAG26SMWoZ/ZHfAZuJ8ivMl1SHEgess6ouDGeQtc4WMjInlhVZ3VcAPeAd+AX4Ceqf0EvgDv8Cs11hpm4Hfda1xG11q6MbbAG9+S1zFLliMGWIHBF++jNcrRmfUnu8Gd/Bo32Lnp9w4gnt+jZM+4IU0hKzxZ9sJyGiMpPFmWy8ppiqjwJNkLzWmK/no7oBWRnapqdje+8Jym2BLcdEDmp6eQnKYYrMDczJaS00lEZQvMaZZR2YJzmuSJrIGcRhmbWVM5DRnIWsxpyF9ZqzkNacB2TkP6mTWb05DGek5DGtxfn6aXb0+Du1G+wrgo/Mus2aUbknsQMEWVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUovq8le5TLwanBvbj4A2VKRwtjjvLr+g2fAb1wFxUvgFfB89NCy2APfgU/AD1V9BNio6l5E7oOOpb9u0It+5KC4aQNwINyxTonZqWiJVHENytNk3eLBU9ERqc97UovnXwArGj2U8vx34WFJ/AG0vvY6LSeZMAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
|
||||||
<path id="LM_level2_grey-2" data-name="LM level2 grey-2" d="M49,140.61H6.31a5.78,5.78,0,0,1-5.78-5.78h0V105.19C10.89,91.13,18.65,81.32,18.65,81.32h.6s19.46.15,23.86.15a2.29,2.29,0,0,1,2.38,1L54.75,92v42.8A5.78,5.78,0,0,1,49,140.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
|
||||||
</g>
|
|
||||||
<g id="LM_total" data-name="LM total">
|
|
||||||
<g id="LM_whitepart" data-name="LM whitepart">
|
|
||||||
<g style="clip-path: url(#clip-path-2)">
|
|
||||||
<g id="LM_whitepart_combined" data-name="LM whitepart combined">
|
|
||||||
<path id="LM_whitepart_top" data-name="LM whitepart top" d="M43.48,141l-7.15-7.37L12.54,102.56V87.7L-.52,103.84v31.22l1,7.69Z" transform="translate(0.98 1.9)" style="fill: #f1f1f1"/>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
<g id="Group" transform="translate(5.000000, 87.000000)">
|
||||||
</g>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="47" height="52" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAAAXNSR0IArs4c6QAAAhhJREFUaAXtWttRwzAQxAyfpAWSb4YWoAFqoIBURAH8UAAVhEpMBxD+za6xFMmyQcqNLWnmbmbHj1in3btTYjvXdF13IbUGJvURMx5cA7LNxLkYX/YacN/gYAtc25PL7HzDbQu+R9e9SMBA/gEOnwCKWNJaOH8BDq6Iq3NndMjv4eMeYCaWtFs477OMuU8iWEKpgCOSfQTegC+AtbkGPjHPK3AH9NVziZ0kg3ou2B3Aslkj8pjGGgN3A9j1liwAg+mE6SSWLhtMEZj3jZckYKh7Rp3R3wGeMxyvbtECBvL8xuGi5TZH9IMARQnIXPcBafdElIAh2jnr3uXs7f8roMS6dxX8KaDUuo8SUAN5CpnMQMmL1o3+rAB8kPvHasxz9jjIQOmLdqzEE1BL3bsirICa6n5SAE5WU/eBgNrq3hMwlA4fB3Pc37tczto3a4APCHxQKOIOM0WJEcAx2e/tU4iba10B5lxVWxWQO12aAc2AMAJaQsIAiodrBsQhFDrQDAgDKB6uGRCHUOhAMyAMoHi4ZkAcQqEDzYAwgOLhmgFxCIUO3Azwn/YazONpBLAT5APwOkEKVEN+5Em+v8Y+CRjfyOXofeDksWBPBnszyHNj+jv6bhUcHPGO9IAPjK3dA2Hmndsy8u/AM3DqVMGBbbcZiWCKtkAp1oJI0CtEckHD0/CqneRtRwgvzGwMaNCtRU6BgMxEk6f/AY1G0nHf2MzkAAAAAElFTkSuQmCC"></image>
|
||||||
<g>
|
<path d="M39.16,50.44 L8.07,50.44 C6.5353168,50.4426552 5.06258085,49.834865 3.97645681,48.7506168 C2.89033276,47.6663686 2.2799977,46.1946855 2.28,44.66 L2.28,22.41 C10.98,11.14 17.84,2 17.84,2 L39.16,2 C40.6998701,1.9893432 42.1803327,2.59359794 43.2729596,3.67871541 C44.3655865,4.76383288 44.9800369,6.24009301 44.98,7.78 L44.98,44.66 C44.98,46.1929513 44.3710375,47.6631169 43.2870772,48.7470772 C42.2031169,49.8310375 40.7329513,50.44 39.2,50.44 L39.16,50.44 Z" id="LM_top_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<image width="47" height="52" transform="translate(5 87)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAACXBIWXMAAAsSAAALEgHS3X78AAABnElEQVRoQ+2azXHCMBBG3zIccQuBM5MWoIHUkAJSUQrIJQWkAlIJ6SDYd+UgGWTjHxQHr5TRm9HFIzz75G8Z8KwYY5iKiMjYnr/AdBQrUwVEpADWwGps70Qq4GiMKf2LkwRc8XvgGStxT47AG3DwJZb9+4fxin8BdkAx/InJbHFPWUQuEsaY4IUt9gn4AE6AmWl9A+/AIy49CwJxDbvBxmaOk/cpgAe8fgsWwN5k69acxdc0vvGCBFzud9jT39C6mQY3C7Sado/O6V9xk4By7ge5SQD93PcyKhBj7n0GBWLNvU+vQArFQ49AzE3bpu8JRNu0ba4EYm/aNg2BVHLvcxZIKfc+/hNIJvc+C0gv9z4LF501iUWnpo7QCvtHIaniodkDycTGZ/THXOxkAW2ygDZZQJssoE0W0CYLaJMFtMkC2mQBbbKANv9K4PdDE/PSqLMWqIAvoDEJEiElts7qfEV59iFknbD1PQFFPbexBDDGlCJy4EJs70hL4BN4pW/cpiVRcf/5nxA6Z4WgY+BpxgmsEDqntWDixFYM/ACNRtJx4q2GRAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
</g>
|
||||||
<path id="LM_top_grey-2" data-name="LM top grey-2" d="M43.18,135.54H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.51C15,96.24,21.86,87.1,21.86,87.1H43.18A5.78,5.78,0,0,1,49,92.88h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<g id="LM_top" transform="translate(17.000000, 112.000000)" fill="#6A6A6A" fill-rule="nonzero">
|
||||||
</g>
|
<g id="LM_top_total">
|
||||||
<g id="LM_top" data-name="LM top">
|
<path d="M2.58,1.95 L2.58,29.42 C2.53732346,30.0007732 2.04187943,30.443134 1.46,30.42 C0.901094365,30.4156223 0.441619994,29.9780276 0.41,29.42 L0.41,1.95 C0.449349984,1.38861093 0.909606462,0.949468178 1.47222361,0.93650465 C2.03484076,0.923541121 2.51483504,1.34101911 2.58,1.9 L2.58,1.95 Z M6.19,1.95 L6.19,29.42 C6.2296472,29.8325035 6.03195189,30.231808 5.67986701,30.4503653 C5.32778212,30.6689226 4.88221788,30.6689226 4.53013299,30.4503653 C4.17804811,30.231808 3.9803528,29.8325035 4.02,29.42 L4.02,1.95 C3.9803528,1.53749648 4.17804811,1.138192 4.53013299,0.919634704 C4.88221788,0.701077408 5.32778212,0.701077408 5.67986701,0.919634704 C6.03195189,1.138192 6.2296472,1.53749648 6.19,1.95 Z M9.81,1.95 L9.81,29.42 C9.8496472,29.8325035 9.65195189,30.231808 9.29986701,30.4503653 C8.94778212,30.6689226 8.50221788,30.6689226 8.15013299,30.4503653 C7.79804811,30.231808 7.6003528,29.8325035 7.64,29.42 L7.64,1.95 C7.6003528,1.53749648 7.79804811,1.138192 8.15013299,0.919634704 C8.50221788,0.701077408 8.94778212,0.701077408 9.29986701,0.919634704 C9.65195189,1.138192 9.8496472,1.53749648 9.81,1.95 Z M13.42,1.95 L13.42,29.42 C13.3873113,29.9829764 12.9306072,30.4280683 12.3669758,30.44625 C11.8033444,30.4644316 11.318904,30.0496992 11.25,29.49 L11.25,1.95 C11.2826887,1.38702361 11.7393928,0.941931677 12.3030242,0.923750018 C12.8666556,0.905568359 13.351096,1.3203008 13.42,1.88 L13.42,1.95 Z M17.04,1.95 L17.04,29.42 C17.0513034,30.0199642 16.5796777,30.5182857 15.98,30.54 C15.401933,30.5576338 14.9125708,30.1167669 14.87,29.54 L14.87,1.95 C14.9026887,1.38702361 15.3593928,0.941931677 15.9230242,0.923750018 C16.4866556,0.905568359 16.971096,1.3203008 17.04,1.88 L17.04,1.95 Z" id="LM_top_lines"></path>
|
||||||
<g style="clip-path: url(#clip-path-3)">
|
</g>
|
||||||
<g id="LM_top_total" data-name="LM top total">
|
</g>
|
||||||
<path id="LM_top_lines" data-name="LM top lines" d="M18.6,112.05v27.47a1.08,1.08,0,0,1-1.12,1,1.06,1.06,0,0,1-1.05-1V112.05A1.09,1.09,0,0,1,18.6,112Zm3.61,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.62,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.61,0v27.47a1.09,1.09,0,0,1-2.17.07V112.05a1.09,1.09,0,0,1,2.17-.07Zm3.62,0v27.47A1.1,1.1,0,0,1,32,140.64a1.08,1.08,0,0,1-1.11-1V112.05a1.09,1.09,0,0,1,2.17-.07Z" transform="translate(0.98 1.9)" style="fill: #6a6a6a"/>
|
<circle id="LM_detail_2" fill="#9A9A9A" fill-rule="nonzero" cx="50.32" cy="137.11" r="2.24"></circle>
|
||||||
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="44" y="0" width="38" height="38" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAAAXNSR0IArs4c6QAAAu1JREFUWAnNmD1y1EAQhb1bhJgjsMT8HAEuQGJHRJyOhAwCTmAyQqpMvOsbYDtGvE/Mm+oZaWUtaHfoqt75n/70WquSZtV13dkhtpKF+Y9V38gpbfeq7OSU2RTnsEBauZq7JkHVMIBdyiltgH2SU9oy8CGQs+AEdq4oALyQR5gaFpgMQiOZga/V3gnwzgNT5SRcUguw1/L3cuCAjGlcqV1bV3UYGLgP8q/yu4dUfFRtkpuVWoABCOgYTF6XKvUc1nFhT+VcGH6tGJMqjiqXwN5og6gWAZYwUkqareLV3jRr4Cy6FgHxVv5F/lP+S06alnT2ZG9iEOs8Mrheg5GOV/KPchYvCTS2FzGIRcw+iwajXKszGqo9T0792DYdz6SiYKLTeav62JUeo49Yo+nt06rBU6ezvkin9yUsFsxp5a99ynQqXGFkbSOHI9s6PWgZuJQ/k6NiCwOsAIzK+QHZAgxBLNAmCVb8W1spZjFQrhDIyrUGMyAcmQW4AbFnNigLFuByrlXP1A3AiB1Z+nuuoG0AFUMWLL7n4oSWdd77buSUvXJFB52NrFPcnTy/4qNc7GBCSyuEAq7oaEmWYmeBfM/ljsZwBYfhYCoGGkAOMmi4wcCJ4RAm3/t6ZeqFWqeKB7aa1EpBBIKDsreo3A/14LM+eP8sX+zXX2QZrN/Zb51q/J+v6QHwiSDfyb/Lj/FJyC0Tfe/3A0xOq9b0hrynSi8Xv5X3xxOCGdxOBZwmcFV5ger+ClN1UQOEL/5vqRyAEW1wVsIV6DX5ikEZNyhnHBs59+S/GhcPCAc5KAbgNomiammjZyVMSeclQAEXD3L6YX4OMKD8qPAZyYMnTQPlHDApyEY3aWM2B5Z3LpeqZlulGiDRIhRvHOy5Y/84aay+V7k4OahoMD4jAbS5n3bxIE3tDKX2/b40sjjaLDgW+HNNVYNQ2gC9SI3PKgG0WbnZUF44G84LKAOouw1Mu1aOI4861V43Wf4V3OSOCw7+BmjmA7QisxQnAAAAAElFTkSuQmCC"></image>
|
||||||
|
<circle id="LM_detail_1" fill="#9A9A9A" fill-rule="nonzero" cx="21.66" cy="86.59" r="2.24"></circle>
|
||||||
|
<g id="hole" transform="translate(45.000000, 1.000000)" fill-rule="nonzero">
|
||||||
|
<g id="Group" fill="#D42715">
|
||||||
|
<circle id="LM_red-2" cx="17.96" cy="17.95" r="17.06"></circle>
|
||||||
|
</g>
|
||||||
|
<g id="LM_details_in_red" transform="translate(2.000000, 2.000000)">
|
||||||
|
<circle id="LM_detail_red_hole4" fill="#393939" cx="12.9" cy="27.01" r="3.79"></circle>
|
||||||
|
<circle id="LM_detail_red_hole3" fill="#393939" cx="4.75" cy="12.89" r="3.79"></circle>
|
||||||
|
<circle id="LM_detail_red_hole2" fill="#393939" cx="18.87" cy="4.74" r="3.79"></circle>
|
||||||
|
<circle id="LM_detail_red_hole1" fill="#393939" cx="27.02" cy="18.86" r="3.79"></circle>
|
||||||
|
<path d="M18.18,15.31 C17.9816076,15.2705154 17.8089761,15.149396 17.7043432,14.9762761 C17.5997103,14.8031562 17.5727287,14.5940066 17.63,14.4 C17.84,13.68 17.99,13.07 17.99,13.07 C17.99,13.07 17.82,12.72 16.72,12.43 C15.62,12.14 15.37,12.37 15.37,12.37 L14.98,13.7 C14.98,13.7 14.82,14.42 14.17,14.24 L12.98,13.9 C12.98,13.9 12.58,14.03 12.38,14.96 C12.2599627,15.4271881 12.2395203,15.9143986 12.32,16.39 L13.57,16.72 C13.9132251,16.8260991 14.1147049,17.1808788 14.03,17.53 C13.87,18.14 13.7,18.74 13.7,18.74 C13.7,18.74 13.82,19.04 14.9,19.36 C15.98,19.68 16.32,19.45 16.32,19.45 L16.64,18.23 C16.64,18.23 16.9,17.47 17.64,17.64 C18.04,17.7533333 18.44,17.8833333 18.84,18.03 C19.3790257,17.4116231 19.6330766,16.5950309 19.54,15.78 C18.89,15.55 18.18,15.31 18.18,15.31 Z" id="LM_detail_hole" fill="#1F1F1F"></path>
|
||||||
|
<path d="M15.62,23.13 L14.07,22.9 L12.54,22.33 C12.29437,22.2663058 12.1467122,22.015735 12.21,21.77 L12.76,19.72 C12.8281001,19.4784149 13.0772913,19.3360199 13.32,19.4 L14.77,20 L16.4,20.22 C16.64563,20.2836942 16.7932878,20.534265 16.73,20.78 L16.18,22.83 C16.1519467,22.9468655 16.0773095,23.0471692 15.9734274,23.1076097 C15.8695454,23.1680501 15.7454609,23.1833663 15.63,23.15 L15.62,23.13 Z" id="LM_detail_red4" fill="#393939"></path>
|
||||||
|
<path d="M23.13,16.2 L22.87,17.75 L22.3,19.27 C22.2716803,19.3872072 22.1975067,19.4881458 22.0941102,19.5501837 C21.9907137,19.6122216 21.8667451,19.6301684 21.75,19.6 L19.69,19.05 C19.4484149,18.9818999 19.3060199,18.7327087 19.37,18.49 L19.98,17.05 L20.2,15.42 C20.2283197,15.3027928 20.3024933,15.2018542 20.4058898,15.1398163 C20.5092863,15.0777784 20.6332549,15.0598316 20.75,15.09 L22.75,15.64 C22.9915851,15.7081001 23.1339801,15.9572913 23.07,16.2 L23.13,16.2 Z" id="LM_detail_red3" fill="#393939"></path>
|
||||||
|
<path d="M16.19,8.69 L17.74,8.94 L19.27,9.51 C19.5107539,9.57376787 19.6570302,9.81756168 19.6,10.06 L19.05,12.11 C18.9818999,12.3515851 18.7327087,12.4939801 18.49,12.43 L17.04,11.83 L15.41,11.61 C15.167847,11.5417439 15.0223875,11.2949036 15.08,11.05 L15.63,9 C15.6580533,8.88313454 15.7326905,8.78283079 15.8365726,8.72239033 C15.9404546,8.66194987 16.0645391,8.64663373 16.18,8.68 L16.19,8.69 Z" id="LM_detail_red2" fill="#393939"></path>
|
||||||
|
<path d="M8.68,15.62 L8.98,14.07 L9.55,12.55 C9.57831973,12.4327928 9.65249325,12.3318542 9.75588978,12.2698163 C9.85928631,12.2077784 9.98325491,12.1898316 10.1,12.22 L12.16,12.77 C12.4015851,12.8381001 12.5439801,13.0872913 12.48,13.33 L11.87,14.77 L11.65,16.4 C11.6216803,16.5172072 11.5475067,16.6181458 11.4441102,16.6801837 C11.3407137,16.7422216 11.2167451,16.7601684 11.1,16.73 L9.1,16.18 C8.85841494,16.1118999 8.71601994,15.8627087 8.78,15.62 L8.68,15.62 Z" id="LM_detail_red1" fill="#393939"></path>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
<circle id="LM_detail_2" data-name="LM detail 2" cx="50.32" cy="137.11" r="2.24" style="fill: #9a9a9a"/>
|
|
||||||
<circle id="LM_detail_1" data-name="LM detail 1" cx="21.66" cy="86.59" r="2.24" style="fill: #9a9a9a"/>
|
|
||||||
<g id="hole">
|
|
||||||
<g>
|
|
||||||
<image width="38" height="38" transform="translate(44)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAACXBIWXMAAAsSAAALEgHS3X78AAACRklEQVRYR9WYPXLbMBBGHzgpxRwhTJ3ER0gukMauUvl0btIlhU9gdSkzQ9dWbmBTtTYFdiUA/BGh0ILyzWBAUiTx+C0JYdeJCDlyzrlgdwU02pu2wEb7vSR3IMDNvUahUpgGuNHetAF+aG/aA+dAzoJzztV4gI/EMHOdM+AW2IhIxwxNwqlbNfAZuMXDpTBhmE3pTQ24Be6ANdAdc/HN2A+JW7d4wJphmFTpOTX+Pu/wD7YCWufcpIuDzinYF2K36t6Jp6kjdvFhFFBEooaH+ArcA8/ADh+mJdtO732vY9Uph4iQgjngCviuFx8b5F/bs451hUYxbBWxauCDtqXCOKXp8UbC+cLxp16qvTAS3lLhTJuF9xNBeC2sK84bzlQ2bYXzJ5VOtA1+5n/PvHnsNdT7twmdswmyhEKDGltchF9rKcdMPYMMrjSYyRGwVJQPaaiIpSJek5V0MHrv4D9w7pK0Bf5oT5UeKCghWeJXyQEZvfQ8uljnTHuD7J0r7Zgp4gg/iNKAvQgaXOnQRh+DZWWVbtgPT5RzsJfvhs49apuV8C4sy8jiyF38Mj0AfAt8A37zOinhbLCh7KvjfOHd4d/xO2AtA4l1BKcfx/4CDuFdWh0+4/+l/aARvVqJiHTOuQfd3bJsOULwIGu8AS3wZFNHqtEq00QhB/LXfcIJlabRKpM62HKYnLccsiPrQxlwOlgIlVWjyy0eGlhazbTjcKRwSEZ1cxYcRLXgIeca4Fq3f7JAyRUy4EIlRWuYdo5cKNNJcOfSX2jmA7RYwAeRAAAAAElFTkSuQmCC" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
|
||||||
<circle id="LM_red-2" data-name="LM red-2" cx="62.96" cy="18.95" r="17.06" style="fill: #d42715"/>
|
|
||||||
</g>
|
|
||||||
<g id="LM_details_in_red" data-name="LM details in red">
|
|
||||||
<circle id="LM_detail_red_hole4" data-name="LM detail red hole4" cx="59.9" cy="30.01" r="3.79" style="fill: #393939"/>
|
|
||||||
<circle id="LM_detail_red_hole3" data-name="LM detail red hole3" cx="51.75" cy="15.89" r="3.79" style="fill: #393939"/>
|
|
||||||
<circle id="LM_detail_red_hole2" data-name="LM detail red hole2" cx="65.87" cy="7.74" r="3.79" style="fill: #393939"/>
|
|
||||||
<circle id="LM_detail_red_hole1" data-name="LM detail red hole1" cx="74.02" cy="21.86" r="3.79" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_hole" data-name="LM detail hole" d="M64.2,16.41a.72.72,0,0,1-.55-.91c.21-.72.36-1.33.36-1.33s-.17-.35-1.27-.64-1.35-.06-1.35-.06L61,14.8s-.16.72-.81.54L59,15s-.4.13-.6,1.06a3.44,3.44,0,0,0-.06,1.43l1.25.33a.68.68,0,0,1,.46.81c-.16.61-.33,1.21-.33,1.21s.12.3,1.2.62,1.42.09,1.42.09l.32-1.22s.26-.76,1-.59q.6.17,1.2.39a2.92,2.92,0,0,0,.7-2.25C64.91,16.65,64.2,16.41,64.2,16.41Z" transform="translate(0.98 1.9)" style="fill: #1f1f1f"/>
|
|
||||||
<path id="LM_detail_red4" data-name="LM detail red4" d="M61.64,24.23,60.09,24l-1.53-.57a.46.46,0,0,1-.33-.56h0l.55-2.05a.46.46,0,0,1,.56-.32l1.45.6,1.63.22a.46.46,0,0,1,.33.56h0l-.55,2.05a.44.44,0,0,1-.55.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_red3" data-name="LM detail red3" d="M69.15,17.3l-.26,1.55-.57,1.52a.45.45,0,0,1-.55.33h0l-2.06-.55a.46.46,0,0,1-.32-.56L66,18.15l.22-1.63a.45.45,0,0,1,.55-.33h0l2,.55a.46.46,0,0,1,.32.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_red2" data-name="LM detail red2" d="M62.21,9.79l1.55.25,1.53.57a.46.46,0,0,1,.33.55h0l-.55,2.05a.46.46,0,0,1-.56.32l-1.45-.6-1.63-.22a.47.47,0,0,1-.33-.56h0l.55-2.05a.44.44,0,0,1,.55-.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_red1" data-name="LM detail red1" d="M54.7,16.72,55,15.17l.57-1.52a.45.45,0,0,1,.55-.33h0l2.06.55a.46.46,0,0,1,.32.56l-.61,1.44-.22,1.63a.45.45,0,0,1-.55.33h0l-2-.55a.46.46,0,0,1-.32-.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</svg>
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 20 KiB |
@ -1,94 +1,79 @@
|
|||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
export const LARGE_MOTOR_SVG = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 82 156">
|
export const LARGE_MOTOR_SVG = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<defs>
|
<svg width="82px" height="156px" viewBox="0 0 82 156" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<clipPath id="clip-path" transform="translate(0.98 1.9)">
|
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
|
||||||
<path d="M79,17.05A17.07,17.07,0,0,1,64.92,33.86l.36.39V70c0,.42-.14.4-.39.68L54,81.22v10l.75.78v.79h6.79a4,4,0,0,1,4,4v25.82a4,4,0,0,1-4,4H54.75v8.18A5.79,5.79,0,0,1,49,140.61h-6.5v7.57a4,4,0,0,1-2.9,3.84v1a.6.6,0,0,1-.6.6H12.69a.6.6,0,0,1-.6-.6h0v-1.29a4,4,0,0,1-2.17-3.55v-7.57H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59l13.68.1,0-11.8H26a4,4,0,0,1-4-4V39.79a4,4,0,0,1,4-4h6.78l0-11.77c0-.84.15-.84.46-1.14l10.41-10.1.22-.19a1.53,1.53,0,0,1,1.59.23A17.07,17.07,0,0,1,79,17.05Z" style="fill: none"/>
|
<title>Large Motor</title>
|
||||||
</clipPath>
|
<desc>Created with Sketch.</desc>
|
||||||
<clipPath id="clip-path-2" transform="translate(0.98 1.9)">
|
<defs></defs>
|
||||||
<path d="M49,140.61H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59s19.46.14,23.87.14a2.27,2.27,0,0,1,2.37,1L54.75,92v42.79A5.79,5.79,0,0,1,49,140.61Z" style="fill: none"/>
|
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-66.000000, -54.000000)">
|
||||||
</clipPath>
|
<g id="Large-Motor" transform="translate(66.000000, 54.000000)">
|
||||||
<clipPath id="clip-path-3" transform="translate(0.98 1.9)">
|
<path d="M39.98,155.52 L13.67,155.52 C13.3386292,155.52 13.07,155.251371 13.07,154.92 L13.07,149.62 C13.07,149.288629 13.3386292,149.02 13.67,149.02 L39.98,149.02 C40.3113708,149.02 40.58,149.288629 40.58,149.62 L40.58,154.9 C40.5854219,155.062566 40.5246096,155.220368 40.4114947,155.337253 C40.2983799,155.454138 40.1426565,155.52009 39.98,155.52 Z" id="LM_back2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path d="M43.18,135.24H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.21C15,95.94,21.86,86.8,21.86,86.8H43.18A5.78,5.78,0,0,1,49,92.58h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" style="fill: none"/>
|
<g id="Group" transform="translate(9.000000, 136.000000)">
|
||||||
</clipPath>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAAAXNSR0IArs4c6QAAAMRJREFUSA3tlrERwjAMRW2OEmYgPQMwFrMwAytBT1iB9OY/x05J1IAopLtv2Y5yevfPhXIpJWVF+oMQSwEDmJ00tKzkFpM6P8Q1bbUZpLN0lLwcw6G7dJFuQOEUQCfJE0rtK0sCigCmq144LIshG4fmqy0DatWiVhBOhVNWB6x18abCKasD1rr+puocY/3pS3ULA1DMMU/pJfHBQ/SGAZY6JYzKVw6Kw5x+vnYGcsptHN5rDxCzlUfg0CgWHJuhPCg+9XwDDy9ID0K8XgsAAAAASUVORK5CYII="></image>
|
||||||
</defs>
|
<path d="M33.84,18.07 L2.51,18.07 C2.17862915,18.07 1.91,17.8013708 1.91,17.47 L1.91,2.77 C1.91,2.43862915 2.17862915,2.17 2.51,2.17 L33.84,2.17 C34.1713708,2.17 34.44,2.43862915 34.44,2.77 L34.44,17.47 C34.44,17.8013708 34.1713708,18.07 33.84,18.07 Z" id="LM_back1-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<title>Large Motor</title>
|
</g>
|
||||||
<g style="isolation: isolate">
|
<g id="LM_rightside" transform="translate(22.000000, 37.000000)" fill-rule="nonzero">
|
||||||
<g id="e13b39e7-895d-4931-9be9-7aecaf709784">
|
<path d="M12.06,34.51 L6.45,34.51 C4.99937339,34.5153259 3.60647912,33.9421088 2.57978624,32.9172929 C1.55309337,31.892477 0.977328505,30.5006339 0.98,29.05 L0.98,6.15 C0.977339027,4.70110385 1.55173283,3.31078487 2.57625885,2.28625885 C3.60078487,1.26173283 4.99110385,0.687339027 6.44,0.69 L12.05,0.69 C15.0654747,0.69 17.51,3.13452527 17.51,6.15 L17.51,29.05 C17.5126553,30.4971617 16.939633,31.8859609 15.9172718,32.910198 C14.8949106,33.9344351 13.5071641,34.5100024 12.06,34.51 Z" id="LM_rightside5" fill="#A8AAA8"></path>
|
||||||
<g style="clip-path: url(#clip-path)">
|
<circle id="LM_rightside4" fill="#FFFFFF" cx="6.3" cy="29.21" r="3.79"></circle>
|
||||||
<g id="Large_Motor" data-name="Large Motor">
|
<circle id="LM_rightside3" fill="#FFFFFF" cx="6.3" cy="6" r="3.79"></circle>
|
||||||
<path id="LM_back2" data-name="LM back2" d="M39,153.62H12.69a.6.6,0,0,1-.6-.6h0v-5.3a.6.6,0,0,1,.6-.6H39a.6.6,0,0,1,.6.6V153A.6.6,0,0,1,39,153.62Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<path d="M3.38,24.59 C4.07351535,24.1313154 4.88857129,23.8909784 5.72,23.9 C6.76862292,23.8298668 7.81405119,24.0772848 8.72,24.61 C9.97,25.54 9.95,24.51 9.95,24.51 L9.95,22.71 C9.95,22.26 9.39,21.86 8.72,22.25 L7.72,22.83 C7.72,22.83 7.36,23.02 7.36,22.5 L7.36,19.9 C7.36,19.9 7.36,19.11 8.09,19.13 C8.82,19.15 9.47,19.13 9.47,19.13 C9.47,19.13 9.76,18.88 9.76,17.74 C9.76,16.6 9.47,16.42 9.47,16.42 L8.08,16.42 C8.08,16.42 7.35,16.42 7.35,15.77 L7.35,14.47 C7.35,14.47 7.12,14.11 6.18,14.17 C5.6978322,14.1741563 5.22153417,14.2762201 4.78,14.47 L4.78,15.77 C4.77453579,16.1305967 4.48063814,16.4200414 4.12,16.42 C3.49,16.42 2.86,16.42 2.86,16.42 C2.86,16.42 2.61,16.61 2.57,17.74 C2.53,18.87 2.86,19.13 2.86,19.13 L4.12,19.13 C4.12,19.13 4.92,19.18 4.94,19.9 C4.96,20.62 4.94,22.52 4.94,22.52 C4.94,22.52 4.94,23.03 4.6,22.85 L3.39,22.27 C3.39,22.27 2.56,21.86 2.57,22.73 C2.58,23.6 2.57,24.53 2.57,24.53 C2.57,24.53 2.65,25.02 3.38,24.59 Z" id="LM_rightside2" fill="#FFFFFF"></path>
|
||||||
<g>
|
<path d="M10.23,12.79 C10.1913976,13.0147775 10.0630557,13.2141964 9.87446015,13.3424414 C9.68586455,13.4706864 9.453229,13.5167322 9.23,13.47 C9.14591061,13.4523039 9.06499079,13.421959 8.99,13.38 C8.1099436,12.9124008 7.1357966,12.6492102 6.14,12.61 C5.162003,12.5962776 4.20061308,12.8635231 3.37,13.38 C2.54,13.78 2.3,12.79 2.3,12.79 L2.3,11.03 C2.33192589,10.6400455 2.66941985,10.3469587 3.06,10.37 C3.16998614,10.3773249 3.27646607,10.4116733 3.37,10.47 C4.20732336,10.980005 5.16044012,11.2690368 6.14,11.31 C7.13850164,11.2335413 8.10964397,10.9473099 8.99,10.47 C8.99,10.47 10.17,10.23 10.19,11.03 C10.21,11.83 10.23,12.79 10.23,12.79 Z" id="LM_rightside1" fill="#FFFFFF"></path>
|
||||||
<image width="36" height="20" transform="translate(9 136)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAACXBIWXMAAAsSAAALEgHS3X78AAAAp0lEQVRIS+3WsW3DMBBG4Y+GSmcGp/cAHsuzeIasFPdWVpD6c0FKcBWwOxV8wIEgSIAPvOL+EhFKKcUBiIiAgjO+25rJildErJMqdMdVlcwg8MQDv5P6Q1fc5ErRujW1TfmoLPa3T//dymJI9TKkehlSvQypXoZUL5vUNhAz2R1Oao75w9IOMmpRHVZqSpjxo3KRw+YwQ2lx+EsVykqfK+aIWGhSR+MNDy9ID5XUCOsAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
</g>
|
||||||
<path id="LM_back1-2" data-name="LM back1-2" d="M41.86,152.17H10.53a.6.6,0,0,1-.6-.6v-14.7a.6.6,0,0,1,.6-.6H41.86a.6.6,0,0,1,.6.6h0v14.7A.6.6,0,0,1,41.86,152.17Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<g id="Group" transform="translate(32.000000, 12.000000)">
|
||||||
</g>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="76" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAAAXNSR0IArs4c6QAAAnlJREFUaAXtmsFRwzAQRROGI6EEwhmGEqABTtyhACqiAC4cOVBBaAEKCB0AuYf/hdbjBMcrbYTlw+7MZp3IWr98OZIn2ul6vZ7k2BTG89Evr2PGRaY5ucEzQ+55zL9EXP0HXDJUBLoCyG2EekZ8hy8B9h0/KxKSoFpA97jqJZxDSKUI9QhflAQ7RMJe2wKiUhxC2jn8BH7ENzivGFgvVA9Q4MDLMZygwUqB7YRSgISDkcoVBeuEygASuLJgnBLaHr/5NeIL/AvO+SjVP3HuE/wCHn5E7dypxwfo3JhBoaZvPKBiZ9F5bDOhR28msSrUVpLqUmXmmkn+nBiGjp1jEsuQtYHkeC8wsBQH2huMv745/A7Omdp+H6DzljGXaaogFGdkzswlgZAumAlM5qnwOCKZCsdsMIEqzPEnXRbYUFCkTAYbEioZbGioJLAaUCpYLahesJpQO8FqQwkYV5MVnM/9bxuPLjyjknG64KoSnvfHAkUtmlVlTFAEC+ZQooQWXSlNIWl3pUQJLbpSmkLS7kqJElp0pTSFpN2VEiW06EppCkm7KyVKaNGV0hSSdldKlNCiK6UpJO2ulCihRVdKU0jaXSlRQouulKaQtI9JKW7JBRsLFCtAPuD8M3YyBigCvcJZCcJ/h6tDEWgBf2DEPnOomampVCcQ4KoptROoFlQvUA0oFWhoqCSgIaGSgYaCygIaAiobiFCy3yelIPyM1uwo/b41vZqAeCVCcb1hwR+NMNxzY6lJ2HtDtBiBuHRszNSpiQTiFB0EgkA3cEarcQ0zVzWGajAUc7WHq4RSYetV1rLcb9ZZ57kFmZsznA8g3qcm64QyZSrY6Qey39wRVmjftAAAAABJRU5ErkJggg=="></image>
|
||||||
<g id="LM_rightside" data-name="LM rightside">
|
<path d="M33.89,60.6 L20.48,73.53 L1.91,72.9 L1.74,13.9 C1.74,13.06 1.9,13.06 2.2,12.77 L12.62,2.67 L12.83,2.48 C13.42,2.08 14.83,2.59 14.83,3.43 L34.27,24.15 L34.27,59.9 C34.28,60.34 34.14,60.33 33.89,60.6 Z" id="LM_level4-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path id="LM_rightside5" data-name="LM rightside5" d="M33.08,69.61H27.47A5.45,5.45,0,0,1,22,64.15h0V41.25a5.45,5.45,0,0,1,5.46-5.46h5.61a5.46,5.46,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,33.08,69.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
</g>
|
||||||
<circle id="LM_rightside4" data-name="LM rightside4" cx="28.3" cy="66.21" r="3.79" style="fill: #fff"/>
|
<g id="Group" transform="translate(32.000000, 69.000000)">
|
||||||
<circle id="LM_rightside3" data-name="LM rightside3" cx="28.3" cy="43" r="3.79" style="fill: #fff"/>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="25" height="27" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAAAXNSR0IArs4c6QAAAZhJREFUSA3tlj1SwzAQRnEmJanogYoChiOQC1BxAA7AcTgDDQfgBLlDekxNQ5LefE/WeizHGa9l07Ezny3L2n36W9lFVVVnXStk3Trvs+IdB5Rz0a0XY6X6K+ncG7zV7qByqZj7Vl0oJqAIWevNswRsrJVyeJM2XdjSIrUgL6p7kBjZWLuVQ5gJxUthcepYk3vpXfqRmOdc7eT7IT1KK+IjGxG9pzcoZyRyawx/ZiSsl0a2FahaxCnjBetyLWXvOPmaAbuUmg210AOLDgTY1NEoRGNJhwFBhT4npKFZARCW0Ouqea8GmjdqT7R/UM+k+KosYe0U8HhlbRxAZPA2EoaCkArkHfehtjFkfQP0Kb1KTRarfMqAPEl3EmV37i11DB04j+TkMdohQJwmfFJcsLBGHHpy8Ng+dupLjZlyzAWzzVC7OK6xUzsBN63mg7DRIAsuIKNzw7JBAMfAJoFOwPjcHO3gyaAeGJuEL3XyJzQLqAMrI+imDUt+t3CYatognBhM3YX0rXUMaTA7yDoKMKZCqPozkAHt/gsh4I9CsIZ80gAAAABJRU5ErkJggg=="></image>
|
||||||
<path id="LM_rightside2" data-name="LM rightside2" d="M24.4,59.69A4.16,4.16,0,0,1,26.74,59a5.23,5.23,0,0,1,3,.71c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.85-1.23-.46l-1,.58s-.36.19-.36-.33V55s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.39-.29-1.32-.29-1.32H29.1s-.73,0-.73-.65v-1.3s-.23-.36-1.17-.3a3.56,3.56,0,0,0-1.4.3v1.3a.66.66,0,0,1-.66.65c-.63,0-1.26,0-1.26,0s-.25.19-.29,1.32.29,1.39.29,1.39h1.26s.8.05.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.41-.82.46,0,1.8,0,1.8S23.67,60.12,24.4,59.69Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
<path d="M22.9800421,24.9 L22.98,7.6 C22.9824406,7.20649401 22.8788083,6.81960003 22.68,6.48 C22.4,6.21 19.16,2.86 19.16,2.86 C18.8448174,2.57277854 18.4252272,2.42809227 18,2.46 C17.25,2.46 6.38,2.46 6.38,2.46 L1.98,7.16 L1.98,15.16 L12.64,15.73 L22.9800421,24.9 Z" id="LM_level3-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path id="LM_rightside1" data-name="LM rightside1" d="M31.25,47.89a.84.84,0,0,1-1,.68.85.85,0,0,1-.24-.09,6.63,6.63,0,0,0-2.85-.77,5.11,5.11,0,0,0-2.77.77c-.83.4-1.07-.59-1.07-.59V46.13a.72.72,0,0,1,.76-.66.67.67,0,0,1,.31.1,5.79,5.79,0,0,0,2.77.84,7.12,7.12,0,0,0,2.85-.84s1.18-.24,1.2.56S31.25,47.89,31.25,47.89Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
</g>
|
||||||
</g>
|
<g id="LM_leftside" transform="translate(49.000000, 94.000000)" fill-rule="nonzero">
|
||||||
<g>
|
<path d="M12.06,34.54 L6.45,34.54 C4.99937339,34.5453259 3.60647912,33.9721088 2.57978624,32.9472929 C1.55309337,31.922477 0.977328505,30.5306339 0.98,29.08 L0.98,6.18 C0.98,3.16452527 3.42452527,0.72 6.44,0.72 L12.05,0.72 C15.0631921,0.725503561 17.5044964,3.16680786 17.51,6.18 L17.51,29.08 C17.5126553,30.5271617 16.939633,31.9159609 15.9172718,32.940198 C14.8949106,33.9644351 13.5071641,34.5400024 12.06,34.54 Z" id="LM_leftside5" fill="#A8AAA8"></path>
|
||||||
<image width="36" height="76" transform="translate(32 12)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAACXBIWXMAAAsSAAALEgHS3X78AAACAElEQVRoQ+3avVHDMBiA4VdcypgREmo4RggLpKKHAZiIAWgoKZggrEAGCBsQpxeFpNgJ/vkkK5YLvXe6g2Cb53zE9oVPaa3xSSmlALTvjh4pn2MrpQpgab/dAYdL4MQoC3oAnuxLH8AW2Gmty9YdAxKhaqAXYAUozJnaAm/AJiZs1rfBGegBKOyP7oAFMLfbRYN1ojpAYM7WtX3dbR8F1orqAdVz27n9BsMaUR4gV1yY1vpkYX7BGvgE9oD2WL/AO3CPfROFrKs6MOAMnVcAt3b57lsV6QzV194eYw0UfWelacUGRYFdAjQYNsPcy54xV+rwv4P/Bb8jZ5gr8oK4IFcQzF2nVOdWw/KG9d77IuUFGwsFHrAxUSCEjY0CASwFCnpgqVDQAUuJghZYahQY2Ao4YJ77v08eXRJWUHvenwoKaneVKaGOZZS0jJKWUdIySlpGScsoaRklLaOkZZS0jJKWUdIySlpGScsoaRklLaOkTQml3RdTQZXAD+bD2EmgSuALMwmyg/SoEtgAr9RGU1KiGkGQDtUKgjSoThCMj+oFwbgoEQjGQ4lBMA7KCwSXR3mDoPonpBsFccWYUwgCgUEdMAN/YDBzzKjJvG0nQe7W4Q2CCnFDhVgCj1TznCHtGDDVqLTWxylXW4wzdWDA/GfjnOcZMijddGBhouHTsfsDst/cEY24RzwAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
<circle id="LM_leftside4" fill="#FFFFFF" cx="12.67" cy="29.24" r="3.79"></circle>
|
||||||
<path id="LM_level4-2" data-name="LM level4-2" d="M64.91,70.7,51.5,83.63,32.93,83,32.76,24c0-.84.16-.84.46-1.13l10.42-10.1.21-.19c.59-.4,2,.11,2,.95L65.29,34.25V70C65.3,70.44,65.16,70.43,64.91,70.7Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<circle id="LM_leftside3" fill="#FFFFFF" cx="12.67" cy="6.03" r="3.79"></circle>
|
||||||
</g>
|
<path d="M9.75,24.62 C10.4421225,24.1572205 11.2574415,23.9133217 12.09,23.92 C13.1380484,23.8411302 14.1850856,24.0854388 15.09,24.62 C16.34,25.55 16.32,24.52 16.32,24.52 L16.32,22.72 C16.32,22.27 15.76,21.88 15.09,22.26 L14.09,22.84 C14.09,22.84 13.73,23.03 13.73,22.51 L13.73,19.9 C13.73,19.9 13.73,19.11 14.46,19.13 C15.19,19.15 15.84,19.13 15.84,19.13 C15.84,19.13 16.13,18.88 16.13,17.75 C16.13,16.62 15.84,16.42 15.84,16.42 L14.45,16.42 C14.45,16.42 13.72,16.42 13.72,15.78 L13.72,14.48 C13.72,14.48 13.49,14.12 12.55,14.17 C12.0671703,14.1775857 11.5908982,14.283046 11.15,14.48 L11.15,15.78 C11.1391868,16.1366743 10.8468382,16.4201639 10.49,16.42 L9.23,16.42 C9.23,16.42 8.98,16.62 8.94,17.75 C8.9,18.88 9.23,19.13 9.23,19.13 L10.49,19.13 C10.49,19.13 11.29,19.13 11.31,19.9 C11.33,20.67 11.31,22.52 11.31,22.52 C11.31,22.52 11.31,23.03 10.97,22.85 L9.76,22.27 C9.76,22.27 8.93,21.87 8.94,22.73 C8.95,23.59 8.94,24.53 8.94,24.53 C8.94,24.53 8.98,25.06 9.75,24.62 Z" id="LM_leftside2" fill="#FFFFFF"></path>
|
||||||
<g>
|
<path d="M16.6,12.82 C16.5640845,13.0461448 16.4363396,13.2474057 16.2469908,13.3761629 C16.057642,13.5049201 15.8235128,13.5497335 15.6,13.5 C15.5157002,13.4885804 15.4342916,13.4614442 15.36,13.42 C14.4821686,12.9467916 13.506699,12.6832437 12.51,12.65 C11.5311949,12.6299456 10.5680375,12.8976825 9.74,13.42 C8.91,13.82 8.67,12.82 8.67,12.82 L8.67,11.06 C8.70188656,10.6714097 9.04116607,10.3812364 9.43,10.41 C9.53837526,10.4186243 9.6438555,10.4492476 9.74,10.5 C10.5773234,11.010005 11.5304401,11.2990368 12.51,11.34 C13.5091637,11.2671668 14.4810541,10.9807149 15.36,10.5 C15.36,10.5 16.54,10.26 16.56,11.06 C16.58,11.86 16.6,12.82 16.6,12.82 Z" id="LM_leftside1" fill="#FFFFFF"></path>
|
||||||
<image width="25" height="27" transform="translate(32 69)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAACXBIWXMAAAsSAAALEgHS3X78AAABYUlEQVRIS+2WvVXDMBRG7/NxGVf0CRVFchghWSAVA2QAxmEGGgZgguzgHlPTELv/KCSD/BMs2wkV9xwf2/LPlZ70JJkk2piZdQojUd8PAWuXm1kGrIBF3wcDVEAhqWw/aIi8ZAcccLKxFMAzcGzL0voikDwCWyBjPGt8JMysKfMtMuAeeAE+Ac04TsArsAcySUj6blGGq82aaS0JyXARqYDCzHJJSnzItrh+ucW1bi4ZsCQYUAmu0w9M75dzNCqc4KxLLivpkPjzJcL1Kwl/xL9oMnXC1lkdw6SBk+IyOPf3Qz9Z8DOzD73bIAXegCfiloUV8ABs/HV07qWSKjPLiSP3xwY3m+yIlKVwflXsofSVeseFHCJlKSPxlTqZ2TEoHpSNFtVIKsfIJotgnGyWCHplW3pG8GwRdGQVbqXu35zMJZAVONEdgayzr5uL33wugBvgQ1IFVxDVmJmF+Xk1UZsvIeCPQjWq5BoAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
</g>
|
||||||
<path id="LM_level3-2" data-name="LM level3-2" d="M54,92V74.7a2.19,2.19,0,0,0-.3-1.12c-.28-.27-3.52-3.62-3.52-3.62a1.55,1.55,0,0,0-1.16-.4c-.75,0-11.62,0-11.62,0L33,74.26v8l10.66.57Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<g id="Group" transform="translate(0.000000, 81.000000)">
|
||||||
</g>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="58" height="64" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAAAXNSR0IArs4c6QAAAqRJREFUaAXtm01OwzAQhSlUYgNbJDalaxBHgAtwBg7AiVixYsOODScoN0DqAcoNoJUQq/CecaK64zhOm7T1yCNNf+zUns/P4xjkDIqiOOjKBrCu2mpqB3G3Dnywxm+8cYDzFBUX8BPvBd0WLtDcDL5oA90JrAW9Ref3cAL3bQR9hU/hMwDPYzrcGHYJ9AEd3sCpcN9WKkvYZ/gkBni4SVQroFR2G6AMmf1cwUdwkzaIpRmYObuO2w7v8P4G/4ZzwdiFf6HfF/g13MzUOp5DXNDaMIpcdcdw5ui2pi668hpVvrQenFlrwaLh6A684XVb6Ay8TS1vD61z1jZGNanqGM7Odm0cfK4ZxhCjN39bwVpQNsqVd5sL0j9F+LUROBoWoM50Qb/B/AjH1VttEDga1sJFLQS9ocQ1XAscBWun777laQidwIzXbD4Q/xS3o6JxNbag+5qnTcAjXFDt1YOwAE0hT0PAzp0iCItWOB1SyNMQcFVXC2unb0p5WkHVffDCJpyndZymXMAqyNNaYAGLK1Xl6TK5A6sxT72wWvNUwGrOUwGLArV56sBqz1MHFl/4r0/+Ic4NBBVWa1yNuVHmhlk1KBUsbz3OhpkVGq2E1cgmmDKsGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjFJZnu3XaA4XYXly8xMe9WxMQiNCHnKRz9gRXn/gfILiDH4OP4anbgR9hz/BP3D69pdAQ3yY41zFhF+spX7coAR9BI/zrIA5XL0CTNl5ziJVmyFw71NczuNp9uQMQasDyQkSm9PjFHA1dgeWlfYA2Op1SX0HqLMKl8EL2LJC4/sftL72OnfR538AAAAASUVORK5CYII="></image>
|
||||||
<g id="LM_leftside" data-name="LM leftside">
|
<path d="M49.98,61.51 L7.29,61.51 C4.09779415,61.51 1.51,58.9222059 1.51,55.73 L1.51,26.09 C11.87,12.03 19.63,2.22 19.63,2.22 L20.23,2.22 C20.23,2.22 39.69,2.37 44.09,2.37 C45.013529,2.18179526 45.9580478,2.5786519 46.47,3.37 L55.73,12.9 L55.73,55.7 C55.7379772,57.2329575 55.1366519,58.7062958 54.0583133,59.7958867 C52.9799747,60.8854775 51.5129577,61.5020641 49.98,61.51 Z" id="LM_level2_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<path id="LM_leftside5" data-name="LM leftside5" d="M60.08,126.64H54.47A5.45,5.45,0,0,1,49,121.18h0V98.28a5.46,5.46,0,0,1,5.46-5.46h5.61a5.47,5.47,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,60.08,126.64Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
</g>
|
||||||
<circle id="LM_leftside4" data-name="LM leftside4" cx="61.67" cy="123.24" r="3.79" style="fill: #fff"/>
|
<g id="LM_total">
|
||||||
<circle id="LM_leftside3" data-name="LM leftside3" cx="61.67" cy="100.03" r="3.79" style="fill: #fff"/>
|
<g id="LM_whitepart" transform="translate(0.000000, 89.000000)" fill="#F1F1F1" fill-rule="nonzero">
|
||||||
<path id="LM_leftside2" data-name="LM leftside2" d="M57.77,116.72a4.15,4.15,0,0,1,2.34-.7,5.14,5.14,0,0,1,3,.7c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.84-1.23-.46l-1,.58s-.36.19-.36-.33V112s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.38-.29-1.33-.29-1.33H62.47s-.73,0-.73-.64v-1.3s-.23-.36-1.17-.31a3.57,3.57,0,0,0-1.4.31v1.3a.66.66,0,0,1-.66.64H57.25s-.25.2-.29,1.33.29,1.38.29,1.38h1.26s.8,0,.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.4-.82.46,0,1.8,0,1.8S57,117.16,57.77,116.72Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
<g id="LM_whitepart_combined">
|
||||||
<path id="LM_leftside1" data-name="LM leftside1" d="M64.62,104.92a.83.83,0,0,1-1,.68.68.68,0,0,1-.24-.08,6.46,6.46,0,0,0-2.85-.77,5,5,0,0,0-2.77.77c-.83.4-1.07-.6-1.07-.6v-1.76a.71.71,0,0,1,.76-.65.8.8,0,0,1,.31.09,5.79,5.79,0,0,0,2.77.84,7,7,0,0,0,2.85-.84s1.18-.24,1.2.56S64.62,104.92,64.62,104.92Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
|
<polygon id="LM_whitepart_top" points="44.46 53.9 37.31 46.53 13.52 15.46 13.52 0.6 0.46 16.74 0.46 47.96 1.46 55.65"></polygon>
|
||||||
</g>
|
</g>
|
||||||
<g>
|
|
||||||
<image width="58" height="64" transform="translate(0 81)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAACXBIWXMAAAsSAAALEgHS3X78AAACFElEQVRoQ+2bQY7TMBSGvxcqsaFbJDbDrEEcYeYCcwYOwIlYsWLDjg0nGG6A1ANkbgCNhGb1WNgBpxPbaUjT+smf5E3lxPlq/25S5YmqshQiIrk+S6EzLlxmHDOKiGyB18CLXN8F6IAW6I6RXkTWi94C73HCp6YFvgI7oFXVfaY/sIBsIPoBuAG26SMWoZ/ZHfAZuJ8ivMl1SHEgess6ouDGeQtc4WMjInlhVZ3VcAPeAd+AX4Ceqf0EvgDv8Cs11hpm4Hfda1xG11q6MbbAG9+S1zFLliMGWIHBF++jNcrRmfUnu8Gd/Bo32Lnp9w4gnt+jZM+4IU0hKzxZ9sJyGiMpPFmWy8ppiqjwJNkLzWmK/no7oBWRnapqdje+8Jym2BLcdEDmp6eQnKYYrMDczJaS00lEZQvMaZZR2YJzmuSJrIGcRhmbWVM5DRnIWsxpyF9ZqzkNacB2TkP6mTWb05DGek5DGtxfn6aXb0+Du1G+wrgo/Mus2aUbknsQMEWVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUovq8le5TLwanBvbj4A2VKRwtjjvLr+g2fAb1wFxUvgFfB89NCy2APfgU/AD1V9BNio6l5E7oOOpb9u0It+5KC4aQNwINyxTonZqWiJVHENytNk3eLBU9ERqc97UovnXwArGj2U8vx34WFJ/AG0vvY6LSeZMAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
|
||||||
<path id="LM_level2_grey-2" data-name="LM level2 grey-2" d="M49,140.61H6.31a5.78,5.78,0,0,1-5.78-5.78h0V105.19C10.89,91.13,18.65,81.32,18.65,81.32h.6s19.46.15,23.86.15a2.29,2.29,0,0,1,2.38,1L54.75,92v42.8A5.78,5.78,0,0,1,49,140.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
|
||||||
</g>
|
|
||||||
<g id="LM_total" data-name="LM total">
|
|
||||||
<g id="LM_whitepart" data-name="LM whitepart">
|
|
||||||
<g style="clip-path: url(#clip-path-2)">
|
|
||||||
<g id="LM_whitepart_combined" data-name="LM whitepart combined">
|
|
||||||
<path id="LM_whitepart_top" data-name="LM whitepart top" d="M43.48,141l-7.15-7.37L12.54,102.56V87.7L-.52,103.84v31.22l1,7.69Z" transform="translate(0.98 1.9)" style="fill: #f1f1f1"/>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
<g id="Group" transform="translate(5.000000, 87.000000)">
|
||||||
</g>
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="47" height="52" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAAAXNSR0IArs4c6QAAAhhJREFUaAXtWttRwzAQxAyfpAWSb4YWoAFqoIBURAH8UAAVhEpMBxD+za6xFMmyQcqNLWnmbmbHj1in3btTYjvXdF13IbUGJvURMx5cA7LNxLkYX/YacN/gYAtc25PL7HzDbQu+R9e9SMBA/gEOnwCKWNJaOH8BDq6Iq3NndMjv4eMeYCaWtFs477OMuU8iWEKpgCOSfQTegC+AtbkGPjHPK3AH9NVziZ0kg3ou2B3Aslkj8pjGGgN3A9j1liwAg+mE6SSWLhtMEZj3jZckYKh7Rp3R3wGeMxyvbtECBvL8xuGi5TZH9IMARQnIXPcBafdElIAh2jnr3uXs7f8roMS6dxX8KaDUuo8SUAN5CpnMQMmL1o3+rAB8kPvHasxz9jjIQOmLdqzEE1BL3bsirICa6n5SAE5WU/eBgNrq3hMwlA4fB3Pc37tczto3a4APCHxQKOIOM0WJEcAx2e/tU4iba10B5lxVWxWQO12aAc2AMAJaQsIAiodrBsQhFDrQDAgDKB6uGRCHUOhAMyAMoHi4ZkAcQqEDzYAwgOLhmgFxCIUO3Azwn/YazONpBLAT5APwOkEKVEN+5Em+v8Y+CRjfyOXofeDksWBPBnszyHNj+jv6bhUcHPGO9IAPjK3dA2Hmndsy8u/AM3DqVMGBbbcZiWCKtkAp1oJI0CtEckHD0/CqneRtRwgvzGwMaNCtRU6BgMxEk6f/AY1G0nHf2MzkAAAAAElFTkSuQmCC"></image>
|
||||||
<g>
|
<path d="M39.16,50.44 L8.07,50.44 C6.5353168,50.4426552 5.06258085,49.834865 3.97645681,48.7506168 C2.89033276,47.6663686 2.2799977,46.1946855 2.28,44.66 L2.28,22.41 C10.98,11.14 17.84,2 17.84,2 L39.16,2 C40.6998701,1.9893432 42.1803327,2.59359794 43.2729596,3.67871541 C44.3655865,4.76383288 44.9800369,6.24009301 44.98,7.78 L44.98,44.66 C44.98,46.1929513 44.3710375,47.6631169 43.2870772,48.7470772 C42.2031169,49.8310375 40.7329513,50.44 39.2,50.44 L39.16,50.44 Z" id="LM_top_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
|
||||||
<image width="47" height="52" transform="translate(5 87)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAACXBIWXMAAAsSAAALEgHS3X78AAABnElEQVRoQ+2azXHCMBBG3zIccQuBM5MWoIHUkAJSUQrIJQWkAlIJ6SDYd+UgGWTjHxQHr5TRm9HFIzz75G8Z8KwYY5iKiMjYnr/AdBQrUwVEpADWwGps70Qq4GiMKf2LkwRc8XvgGStxT47AG3DwJZb9+4fxin8BdkAx/InJbHFPWUQuEsaY4IUt9gn4AE6AmWl9A+/AIy49CwJxDbvBxmaOk/cpgAe8fgsWwN5k69acxdc0vvGCBFzud9jT39C6mQY3C7Sado/O6V9xk4By7ge5SQD93PcyKhBj7n0GBWLNvU+vQArFQ49AzE3bpu8JRNu0ba4EYm/aNg2BVHLvcxZIKfc+/hNIJvc+C0gv9z4LF501iUWnpo7QCvtHIaniodkDycTGZ/THXOxkAW2ygDZZQJssoE0W0CYLaJMFtMkC2mQBbbKANv9K4PdDE/PSqLMWqIAvoDEJEiElts7qfEV59iFknbD1PQFFPbexBDDGlCJy4EJs70hL4BN4pW/cpiVRcf/5nxA6Z4WgY+BpxgmsEDqntWDixFYM/ACNRtJx4q2GRAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
</g>
|
||||||
<path id="LM_top_grey-2" data-name="LM top grey-2" d="M43.18,135.54H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.51C15,96.24,21.86,87.1,21.86,87.1H43.18A5.78,5.78,0,0,1,49,92.88h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
|
<g id="LM_top" transform="translate(17.000000, 112.000000)" fill="#6A6A6A" fill-rule="nonzero">
|
||||||
</g>
|
<g id="LM_top_total">
|
||||||
<g id="LM_top" data-name="LM top">
|
<path d="M2.58,1.95 L2.58,29.42 C2.53732346,30.0007732 2.04187943,30.443134 1.46,30.42 C0.901094365,30.4156223 0.441619994,29.9780276 0.41,29.42 L0.41,1.95 C0.449349984,1.38861093 0.909606462,0.949468178 1.47222361,0.93650465 C2.03484076,0.923541121 2.51483504,1.34101911 2.58,1.9 L2.58,1.95 Z M6.19,1.95 L6.19,29.42 C6.2296472,29.8325035 6.03195189,30.231808 5.67986701,30.4503653 C5.32778212,30.6689226 4.88221788,30.6689226 4.53013299,30.4503653 C4.17804811,30.231808 3.9803528,29.8325035 4.02,29.42 L4.02,1.95 C3.9803528,1.53749648 4.17804811,1.138192 4.53013299,0.919634704 C4.88221788,0.701077408 5.32778212,0.701077408 5.67986701,0.919634704 C6.03195189,1.138192 6.2296472,1.53749648 6.19,1.95 Z M9.81,1.95 L9.81,29.42 C9.8496472,29.8325035 9.65195189,30.231808 9.29986701,30.4503653 C8.94778212,30.6689226 8.50221788,30.6689226 8.15013299,30.4503653 C7.79804811,30.231808 7.6003528,29.8325035 7.64,29.42 L7.64,1.95 C7.6003528,1.53749648 7.79804811,1.138192 8.15013299,0.919634704 C8.50221788,0.701077408 8.94778212,0.701077408 9.29986701,0.919634704 C9.65195189,1.138192 9.8496472,1.53749648 9.81,1.95 Z M13.42,1.95 L13.42,29.42 C13.3873113,29.9829764 12.9306072,30.4280683 12.3669758,30.44625 C11.8033444,30.4644316 11.318904,30.0496992 11.25,29.49 L11.25,1.95 C11.2826887,1.38702361 11.7393928,0.941931677 12.3030242,0.923750018 C12.8666556,0.905568359 13.351096,1.3203008 13.42,1.88 L13.42,1.95 Z M17.04,1.95 L17.04,29.42 C17.0513034,30.0199642 16.5796777,30.5182857 15.98,30.54 C15.401933,30.5576338 14.9125708,30.1167669 14.87,29.54 L14.87,1.95 C14.9026887,1.38702361 15.3593928,0.941931677 15.9230242,0.923750018 C16.4866556,0.905568359 16.971096,1.3203008 17.04,1.88 L17.04,1.95 Z" id="LM_top_lines"></path>
|
||||||
<g style="clip-path: url(#clip-path-3)">
|
</g>
|
||||||
<g id="LM_top_total" data-name="LM top total">
|
</g>
|
||||||
<path id="LM_top_lines" data-name="LM top lines" d="M18.6,112.05v27.47a1.08,1.08,0,0,1-1.12,1,1.06,1.06,0,0,1-1.05-1V112.05A1.09,1.09,0,0,1,18.6,112Zm3.61,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.62,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.61,0v27.47a1.09,1.09,0,0,1-2.17.07V112.05a1.09,1.09,0,0,1,2.17-.07Zm3.62,0v27.47A1.1,1.1,0,0,1,32,140.64a1.08,1.08,0,0,1-1.11-1V112.05a1.09,1.09,0,0,1,2.17-.07Z" transform="translate(0.98 1.9)" style="fill: #6a6a6a"/>
|
<circle id="LM_detail_2" fill="#9A9A9A" fill-rule="nonzero" cx="50.32" cy="137.11" r="2.24"></circle>
|
||||||
|
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="44" y="0" width="38" height="38" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAAAXNSR0IArs4c6QAAAu1JREFUWAnNmD1y1EAQhb1bhJgjsMT8HAEuQGJHRJyOhAwCTmAyQqpMvOsbYDtGvE/Mm+oZaWUtaHfoqt75n/70WquSZtV13dkhtpKF+Y9V38gpbfeq7OSU2RTnsEBauZq7JkHVMIBdyiltgH2SU9oy8CGQs+AEdq4oALyQR5gaFpgMQiOZga/V3gnwzgNT5SRcUguw1/L3cuCAjGlcqV1bV3UYGLgP8q/yu4dUfFRtkpuVWoABCOgYTF6XKvUc1nFhT+VcGH6tGJMqjiqXwN5og6gWAZYwUkqareLV3jRr4Cy6FgHxVv5F/lP+S06alnT2ZG9iEOs8Mrheg5GOV/KPchYvCTS2FzGIRcw+iwajXKszGqo9T0792DYdz6SiYKLTeav62JUeo49Yo+nt06rBU6ezvkin9yUsFsxp5a99ynQqXGFkbSOHI9s6PWgZuJQ/k6NiCwOsAIzK+QHZAgxBLNAmCVb8W1spZjFQrhDIyrUGMyAcmQW4AbFnNigLFuByrlXP1A3AiB1Z+nuuoG0AFUMWLL7n4oSWdd77buSUvXJFB52NrFPcnTy/4qNc7GBCSyuEAq7oaEmWYmeBfM/ljsZwBYfhYCoGGkAOMmi4wcCJ4RAm3/t6ZeqFWqeKB7aa1EpBBIKDsreo3A/14LM+eP8sX+zXX2QZrN/Zb51q/J+v6QHwiSDfyb/Lj/FJyC0Tfe/3A0xOq9b0hrynSi8Xv5X3xxOCGdxOBZwmcFV5ger+ClN1UQOEL/5vqRyAEW1wVsIV6DX5ikEZNyhnHBs59+S/GhcPCAc5KAbgNomiammjZyVMSeclQAEXD3L6YX4OMKD8qPAZyYMnTQPlHDApyEY3aWM2B5Z3LpeqZlulGiDRIhRvHOy5Y/84aay+V7k4OahoMD4jAbS5n3bxIE3tDKX2/b40sjjaLDgW+HNNVYNQ2gC9SI3PKgG0WbnZUF44G84LKAOouw1Mu1aOI4861V43Wf4V3OSOCw7+BmjmA7QisxQnAAAAAElFTkSuQmCC"></image>
|
||||||
|
<circle id="LM_detail_1" fill="#9A9A9A" fill-rule="nonzero" cx="21.66" cy="86.59" r="2.24"></circle>
|
||||||
|
<g id="hole" transform="translate(45.000000, 1.000000)" fill-rule="nonzero">
|
||||||
|
<g id="Group" fill="#D42715">
|
||||||
|
<circle id="LM_red-2" cx="17.96" cy="17.95" r="17.06"></circle>
|
||||||
|
</g>
|
||||||
|
<g id="LM_details_in_red" transform="translate(2.000000, 2.000000)">
|
||||||
|
<circle id="LM_detail_red_hole4" fill="#393939" cx="12.9" cy="27.01" r="3.79"></circle>
|
||||||
|
<circle id="LM_detail_red_hole3" fill="#393939" cx="4.75" cy="12.89" r="3.79"></circle>
|
||||||
|
<circle id="LM_detail_red_hole2" fill="#393939" cx="18.87" cy="4.74" r="3.79"></circle>
|
||||||
|
<circle id="LM_detail_red_hole1" fill="#393939" cx="27.02" cy="18.86" r="3.79"></circle>
|
||||||
|
<path d="M18.18,15.31 C17.9816076,15.2705154 17.8089761,15.149396 17.7043432,14.9762761 C17.5997103,14.8031562 17.5727287,14.5940066 17.63,14.4 C17.84,13.68 17.99,13.07 17.99,13.07 C17.99,13.07 17.82,12.72 16.72,12.43 C15.62,12.14 15.37,12.37 15.37,12.37 L14.98,13.7 C14.98,13.7 14.82,14.42 14.17,14.24 L12.98,13.9 C12.98,13.9 12.58,14.03 12.38,14.96 C12.2599627,15.4271881 12.2395203,15.9143986 12.32,16.39 L13.57,16.72 C13.9132251,16.8260991 14.1147049,17.1808788 14.03,17.53 C13.87,18.14 13.7,18.74 13.7,18.74 C13.7,18.74 13.82,19.04 14.9,19.36 C15.98,19.68 16.32,19.45 16.32,19.45 L16.64,18.23 C16.64,18.23 16.9,17.47 17.64,17.64 C18.04,17.7533333 18.44,17.8833333 18.84,18.03 C19.3790257,17.4116231 19.6330766,16.5950309 19.54,15.78 C18.89,15.55 18.18,15.31 18.18,15.31 Z" id="LM_detail_hole" fill="#1F1F1F"></path>
|
||||||
|
<path d="M15.62,23.13 L14.07,22.9 L12.54,22.33 C12.29437,22.2663058 12.1467122,22.015735 12.21,21.77 L12.76,19.72 C12.8281001,19.4784149 13.0772913,19.3360199 13.32,19.4 L14.77,20 L16.4,20.22 C16.64563,20.2836942 16.7932878,20.534265 16.73,20.78 L16.18,22.83 C16.1519467,22.9468655 16.0773095,23.0471692 15.9734274,23.1076097 C15.8695454,23.1680501 15.7454609,23.1833663 15.63,23.15 L15.62,23.13 Z" id="LM_detail_red4" fill="#393939"></path>
|
||||||
|
<path d="M23.13,16.2 L22.87,17.75 L22.3,19.27 C22.2716803,19.3872072 22.1975067,19.4881458 22.0941102,19.5501837 C21.9907137,19.6122216 21.8667451,19.6301684 21.75,19.6 L19.69,19.05 C19.4484149,18.9818999 19.3060199,18.7327087 19.37,18.49 L19.98,17.05 L20.2,15.42 C20.2283197,15.3027928 20.3024933,15.2018542 20.4058898,15.1398163 C20.5092863,15.0777784 20.6332549,15.0598316 20.75,15.09 L22.75,15.64 C22.9915851,15.7081001 23.1339801,15.9572913 23.07,16.2 L23.13,16.2 Z" id="LM_detail_red3" fill="#393939"></path>
|
||||||
|
<path d="M16.19,8.69 L17.74,8.94 L19.27,9.51 C19.5107539,9.57376787 19.6570302,9.81756168 19.6,10.06 L19.05,12.11 C18.9818999,12.3515851 18.7327087,12.4939801 18.49,12.43 L17.04,11.83 L15.41,11.61 C15.167847,11.5417439 15.0223875,11.2949036 15.08,11.05 L15.63,9 C15.6580533,8.88313454 15.7326905,8.78283079 15.8365726,8.72239033 C15.9404546,8.66194987 16.0645391,8.64663373 16.18,8.68 L16.19,8.69 Z" id="LM_detail_red2" fill="#393939"></path>
|
||||||
|
<path d="M8.68,15.62 L8.98,14.07 L9.55,12.55 C9.57831973,12.4327928 9.65249325,12.3318542 9.75588978,12.2698163 C9.85928631,12.2077784 9.98325491,12.1898316 10.1,12.22 L12.16,12.77 C12.4015851,12.8381001 12.5439801,13.0872913 12.48,13.33 L11.87,14.77 L11.65,16.4 C11.6216803,16.5172072 11.5475067,16.6181458 11.4441102,16.6801837 C11.3407137,16.7422216 11.2167451,16.7601684 11.1,16.73 L9.1,16.18 C8.85841494,16.1118999 8.71601994,15.8627087 8.78,15.62 L8.68,15.62 Z" id="LM_detail_red1" fill="#393939"></path>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
<circle id="LM_detail_2" data-name="LM detail 2" cx="50.32" cy="137.11" r="2.24" style="fill: #9a9a9a"/>
|
|
||||||
<circle id="LM_detail_1" data-name="LM detail 1" cx="21.66" cy="86.59" r="2.24" style="fill: #9a9a9a"/>
|
|
||||||
<g id="hole">
|
|
||||||
<g>
|
|
||||||
<image width="38" height="38" transform="translate(44)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAACXBIWXMAAAsSAAALEgHS3X78AAACRklEQVRYR9WYPXLbMBBGHzgpxRwhTJ3ER0gukMauUvl0btIlhU9gdSkzQ9dWbmBTtTYFdiUA/BGh0ILyzWBAUiTx+C0JYdeJCDlyzrlgdwU02pu2wEb7vSR3IMDNvUahUpgGuNHetAF+aG/aA+dAzoJzztV4gI/EMHOdM+AW2IhIxwxNwqlbNfAZuMXDpTBhmE3pTQ24Be6ANdAdc/HN2A+JW7d4wJphmFTpOTX+Pu/wD7YCWufcpIuDzinYF2K36t6Jp6kjdvFhFFBEooaH+ArcA8/ADh+mJdtO732vY9Uph4iQgjngCviuFx8b5F/bs451hUYxbBWxauCDtqXCOKXp8UbC+cLxp16qvTAS3lLhTJuF9xNBeC2sK84bzlQ2bYXzJ5VOtA1+5n/PvHnsNdT7twmdswmyhEKDGltchF9rKcdMPYMMrjSYyRGwVJQPaaiIpSJek5V0MHrv4D9w7pK0Bf5oT5UeKCghWeJXyQEZvfQ8uljnTHuD7J0r7Zgp4gg/iNKAvQgaXOnQRh+DZWWVbtgPT5RzsJfvhs49apuV8C4sy8jiyF38Mj0AfAt8A37zOinhbLCh7KvjfOHd4d/xO2AtA4l1BKcfx/4CDuFdWh0+4/+l/aARvVqJiHTOuQfd3bJsOULwIGu8AS3wZFNHqtEq00QhB/LXfcIJlabRKpM62HKYnLccsiPrQxlwOlgIlVWjyy0eGlhazbTjcKRwSEZ1cxYcRLXgIeca4Fq3f7JAyRUy4EIlRWuYdo5cKNNJcOfSX2jmA7RYwAeRAAAAAElFTkSuQmCC" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
|
|
||||||
<circle id="LM_red-2" data-name="LM red-2" cx="62.96" cy="18.95" r="17.06" style="fill: #d42715"/>
|
|
||||||
</g>
|
|
||||||
<g id="LM_details_in_red" data-name="LM details in red">
|
|
||||||
<circle id="LM_detail_red_hole4" data-name="LM detail red hole4" cx="59.9" cy="30.01" r="3.79" style="fill: #393939"/>
|
|
||||||
<circle id="LM_detail_red_hole3" data-name="LM detail red hole3" cx="51.75" cy="15.89" r="3.79" style="fill: #393939"/>
|
|
||||||
<circle id="LM_detail_red_hole2" data-name="LM detail red hole2" cx="65.87" cy="7.74" r="3.79" style="fill: #393939"/>
|
|
||||||
<circle id="LM_detail_red_hole1" data-name="LM detail red hole1" cx="74.02" cy="21.86" r="3.79" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_hole" data-name="LM detail hole" d="M64.2,16.41a.72.72,0,0,1-.55-.91c.21-.72.36-1.33.36-1.33s-.17-.35-1.27-.64-1.35-.06-1.35-.06L61,14.8s-.16.72-.81.54L59,15s-.4.13-.6,1.06a3.44,3.44,0,0,0-.06,1.43l1.25.33a.68.68,0,0,1,.46.81c-.16.61-.33,1.21-.33,1.21s.12.3,1.2.62,1.42.09,1.42.09l.32-1.22s.26-.76,1-.59q.6.17,1.2.39a2.92,2.92,0,0,0,.7-2.25C64.91,16.65,64.2,16.41,64.2,16.41Z" transform="translate(0.98 1.9)" style="fill: #1f1f1f"/>
|
|
||||||
<path id="LM_detail_red4" data-name="LM detail red4" d="M61.64,24.23,60.09,24l-1.53-.57a.46.46,0,0,1-.33-.56h0l.55-2.05a.46.46,0,0,1,.56-.32l1.45.6,1.63.22a.46.46,0,0,1,.33.56h0l-.55,2.05a.44.44,0,0,1-.55.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_red3" data-name="LM detail red3" d="M69.15,17.3l-.26,1.55-.57,1.52a.45.45,0,0,1-.55.33h0l-2.06-.55a.46.46,0,0,1-.32-.56L66,18.15l.22-1.63a.45.45,0,0,1,.55-.33h0l2,.55a.46.46,0,0,1,.32.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_red2" data-name="LM detail red2" d="M62.21,9.79l1.55.25,1.53.57a.46.46,0,0,1,.33.55h0l-.55,2.05a.46.46,0,0,1-.56.32l-1.45-.6-1.63-.22a.47.47,0,0,1-.33-.56h0l.55-2.05a.44.44,0,0,1,.55-.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
<path id="LM_detail_red1" data-name="LM detail red1" d="M54.7,16.72,55,15.17l.57-1.52a.45.45,0,0,1,.55-.33h0l2.06.55a.46.46,0,0,1,.32.56l-.61,1.44-.22,1.63a.45.45,0,0,1-.55.33h0l-2-.55a.46.46,0,0,1-.32-.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
</g>
|
|
||||||
</svg>`;
|
</svg>`;
|
||||||
}
|
}
|
@ -44,12 +44,21 @@ namespace pxsim.visuals {
|
|||||||
}
|
}
|
||||||
.sim-text.number {
|
.sim-text.number {
|
||||||
font-family: Courier, Lato, Work Sans, PT Serif, Source Serif Pro;
|
font-family: Courier, Lato, Work Sans, PT Serif, Source Serif Pro;
|
||||||
font-weight: bold;
|
/*font-weight: bold;*/
|
||||||
}
|
}
|
||||||
.sim-text.inverted {
|
.sim-text.inverted {
|
||||||
fill:#5A5A5A;
|
fill:#5A5A5A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-drag, .sim-text, .sim-text-pin {
|
||||||
|
user-drag: none;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Color Grid */
|
/* Color Grid */
|
||||||
.sim-color-grid-circle:hover {
|
.sim-color-grid-circle:hover {
|
||||||
stroke-width: 0.4;
|
stroke-width: 0.4;
|
||||||
@ -62,6 +71,15 @@ namespace pxsim.visuals {
|
|||||||
fill: gray !important;
|
fill: gray !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Motor slider */
|
||||||
|
.sim-motor-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.sim-motor-btn:hover .btn {
|
||||||
|
stroke-width: 2px;
|
||||||
|
stroke: black !important;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EV3_WIDTH = 99.984346;
|
const EV3_WIDTH = 99.984346;
|
||||||
@ -213,9 +231,8 @@ namespace pxsim.visuals {
|
|||||||
}
|
}
|
||||||
case NodeType.MediumMotor:
|
case NodeType.MediumMotor:
|
||||||
case NodeType.LargeMotor: {
|
case NodeType.LargeMotor: {
|
||||||
// TODO: figure out if the motor is in "input" or "output" mode
|
|
||||||
const state = ev3board().getMotors()[port];
|
const state = ev3board().getMotors()[port];
|
||||||
view = new MotorReporterControl(this.element, this.defs, state, port);
|
view = new MotorSliderControl(this.element, this.defs, state, port);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ namespace pxsim.visuals {
|
|||||||
this.group = svg.elt("g") as SVGGElement;
|
this.group = svg.elt("g") as SVGGElement;
|
||||||
|
|
||||||
const reporterGroup = pxsim.svg.child(this.group, "g");
|
const reporterGroup = pxsim.svg.child(this.group, "g");
|
||||||
reporterGroup.setAttribute("transform", `translate(31, 42)`);
|
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 42)`);
|
||||||
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
|
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'text-anchor': 'middle', 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
|
||||||
|
|
||||||
const sliderGroup = pxsim.svg.child(this.group, "g");
|
const sliderGroup = pxsim.svg.child(this.group, "g");
|
||||||
sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
|
sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
|
||||||
@ -60,12 +60,15 @@ namespace pxsim.visuals {
|
|||||||
}, ev => {
|
}, ev => {
|
||||||
captured = true;
|
captured = true;
|
||||||
if ((ev as MouseEvent).clientY != undefined) {
|
if ((ev as MouseEvent).clientY != undefined) {
|
||||||
|
dragSurface.setAttribute('cursor', '-webkit-grabbing');
|
||||||
this.updateSliderValue(pt, parent, ev as MouseEvent);
|
this.updateSliderValue(pt, parent, ev as MouseEvent);
|
||||||
}
|
}
|
||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
|
dragSurface.setAttribute('cursor', '-webkit-grab');
|
||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
|
dragSurface.setAttribute('cursor', '-webkit-grab');
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.group;
|
return this.group;
|
||||||
|
167
sim/visuals/controls/motorSlider.ts
Normal file
167
sim/visuals/controls/motorSlider.ts
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
|
||||||
|
namespace pxsim.visuals {
|
||||||
|
|
||||||
|
export class MotorSliderControl extends ControlView<MotorNode> {
|
||||||
|
private group: SVGGElement;
|
||||||
|
private gradient: SVGLinearGradientElement;
|
||||||
|
private slider: SVGGElement;
|
||||||
|
|
||||||
|
private reporter: SVGTextElement;
|
||||||
|
|
||||||
|
private dial: SVGGElement;
|
||||||
|
|
||||||
|
private static SLIDER_RADIUS = 100;
|
||||||
|
|
||||||
|
private internalSpeed: number = 0;
|
||||||
|
|
||||||
|
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
|
||||||
|
this.group = svg.elt("g") as SVGGElement;
|
||||||
|
|
||||||
|
const slider = pxsim.svg.child(this.group, 'g', { 'transform': 'translate(25,25)' })
|
||||||
|
const outerCircle = pxsim.svg.child(slider, "circle", {
|
||||||
|
'stroke-dasharray': '565.48', 'stroke-dashoffset': '0',
|
||||||
|
'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent;`,
|
||||||
|
'stroke': '#a8aaa8', 'stroke-width': '1rem'
|
||||||
|
}) as SVGCircleElement;
|
||||||
|
|
||||||
|
this.reporter = pxsim.svg.child(this.group, "text", {
|
||||||
|
'x': this.getInnerWidth() / 2, 'y': this.getInnerHeight() / 2,
|
||||||
|
'text-anchor': 'middle', 'alignment-baseline': 'middle',
|
||||||
|
'style': 'font-size: 50px',
|
||||||
|
'class': 'sim-text inverted number'
|
||||||
|
}) as SVGTextElement;
|
||||||
|
|
||||||
|
this.dial = pxsim.svg.child(slider, "g", { 'cursor': '-webkit-grab' }) as SVGGElement;
|
||||||
|
const handleInner = pxsim.svg.child(this.dial, "g");
|
||||||
|
pxsim.svg.child(handleInner, "circle", { 'cx': 0, 'cy': 0, 'r': 30, 'style': 'fill: #f12a21;' });
|
||||||
|
pxsim.svg.child(handleInner, "circle", { 'cx': 0, 'cy': 0, 'r': 29.5, 'style': 'fill: none;stroke: #b32e29' });
|
||||||
|
|
||||||
|
this.updateDial();
|
||||||
|
|
||||||
|
let pt = parent.createSVGPoint();
|
||||||
|
let captured = false;
|
||||||
|
|
||||||
|
const dragSurface = svg.child(this.group, "rect", {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: this.getInnerWidth(),
|
||||||
|
height: this.getInnerHeight(),
|
||||||
|
opacity: 0,
|
||||||
|
cursor: '-webkit-grab'
|
||||||
|
})
|
||||||
|
|
||||||
|
touchEvents(dragSurface, ev => {
|
||||||
|
if (captured && (ev as MouseEvent).clientY != undefined) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.updateSliderValue(pt, parent, ev as MouseEvent);
|
||||||
|
this.handleSliderMove();
|
||||||
|
}
|
||||||
|
}, ev => {
|
||||||
|
captured = true;
|
||||||
|
if ((ev as MouseEvent).clientY != undefined) {
|
||||||
|
this.updateSliderValue(pt, parent, ev as MouseEvent);
|
||||||
|
this.handleSliderDown();
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
captured = false;
|
||||||
|
this.handleSliderUp();
|
||||||
|
}, () => {
|
||||||
|
captured = false;
|
||||||
|
this.handleSliderUp();
|
||||||
|
})
|
||||||
|
|
||||||
|
return this.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInnerWidth() {
|
||||||
|
return 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInnerHeight() {
|
||||||
|
return 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
private lastPosition: number;
|
||||||
|
private prevVal: number;
|
||||||
|
private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||||
|
let cur = svg.cursorPoint(pt, parent, ev);
|
||||||
|
const coords = {
|
||||||
|
x: cur.x / this.scaleFactor - this.left / this.scaleFactor,
|
||||||
|
y: cur.y / this.scaleFactor - this.top / this.scaleFactor
|
||||||
|
};
|
||||||
|
const radius = MotorSliderControl.SLIDER_RADIUS / 2;
|
||||||
|
const dx = coords.x - radius;
|
||||||
|
const dy = coords.y - radius;
|
||||||
|
const atan = Math.atan(-dy / dx);
|
||||||
|
let deg = Math.ceil(atan * (180 / Math.PI));
|
||||||
|
|
||||||
|
if (dx < 0) {
|
||||||
|
deg -= 270;
|
||||||
|
} else if (dy > 0) {
|
||||||
|
deg -= 450;
|
||||||
|
} else if (dx >= 0 && dy <= 0) {
|
||||||
|
deg = 90 - deg;
|
||||||
|
}
|
||||||
|
const value = Math.abs(Math.ceil((deg % 360) / 360 * this.getMax()));
|
||||||
|
|
||||||
|
this.internalSpeed = value;
|
||||||
|
this.updateDial();
|
||||||
|
|
||||||
|
this.prevVal = deg;
|
||||||
|
this.lastPosition = cur.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSliderDown() {
|
||||||
|
const state = this.state;
|
||||||
|
state.manualMotorDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSliderMove() {
|
||||||
|
this.dial.setAttribute('cursor', '-webkit-grabbing');
|
||||||
|
const state = this.state;
|
||||||
|
state.manualMotorMove(this.internalSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSliderUp() {
|
||||||
|
this.dial.setAttribute('cursor', '-webkit-grab');
|
||||||
|
const state = this.state;
|
||||||
|
state.manualMotorUp();
|
||||||
|
|
||||||
|
this.internalSpeed = 0;
|
||||||
|
this.updateDial();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateDial() {
|
||||||
|
let speed = this.internalSpeed;
|
||||||
|
|
||||||
|
// Update dial position
|
||||||
|
const deg = speed / this.getMax() * 360; // degrees
|
||||||
|
const radius = MotorSliderControl.SLIDER_RADIUS;
|
||||||
|
const dialRadius = 5;
|
||||||
|
const x = Math.ceil((radius - dialRadius) * Math.sin(deg * Math.PI / 180)) + radius;
|
||||||
|
const y = Math.ceil((radius - dialRadius) * -Math.cos(deg * Math.PI / 180)) + radius;
|
||||||
|
this.dial.setAttribute('transform', `translate(${x}, ${y})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateState() {
|
||||||
|
if (!this.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const node = this.state;
|
||||||
|
const speed = node.getSpeed();
|
||||||
|
|
||||||
|
// Update reporter
|
||||||
|
this.reporter.textContent = `${speed}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMin() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMax() {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -173,15 +173,15 @@ namespace pxsim.visuals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inject all ports
|
// Inject all ports
|
||||||
this.setInput(0, new PortView(0, 'A'));
|
this.setInput(0, new PortView(0, '1'));
|
||||||
this.setInput(1, new PortView(1, 'B'));
|
this.setInput(1, new PortView(1, '2'));
|
||||||
this.setInput(2, new PortView(2, 'C'));
|
this.setInput(2, new PortView(2, '3'));
|
||||||
this.setInput(3, new PortView(3, 'D'));
|
this.setInput(3, new PortView(3, '4'));
|
||||||
|
|
||||||
this.setOutput(0, new PortView(0, '1'));
|
this.setOutput(0, new PortView(0, 'A'));
|
||||||
this.setOutput(1, new PortView(1, '2'));
|
this.setOutput(1, new PortView(1, 'B'));
|
||||||
this.setOutput(2, new PortView(2, '3'));
|
this.setOutput(2, new PortView(2, 'C'));
|
||||||
this.setOutput(3, new PortView(3, '4'));
|
this.setOutput(3, new PortView(3, 'D'));
|
||||||
|
|
||||||
return this.contentGroup;
|
return this.contentGroup;
|
||||||
}
|
}
|
||||||
|
@ -34,21 +34,21 @@ namespace pxsim.visuals {
|
|||||||
this.syncedLabelG = pxsim.svg.child(this.element, 'g', {'transform': 'scale(0.5)'}) as SVGGElement;
|
this.syncedLabelG = pxsim.svg.child(this.element, 'g', {'transform': 'scale(0.5)'}) as SVGGElement;
|
||||||
pxsim.svg.child(this.syncedLabelG, 'rect', {'rx': 15, 'ry': 15, 'x': 0, 'y': 0, 'width': 84, 'height': 34, 'fill': '#A8A9A8'});
|
pxsim.svg.child(this.syncedLabelG, 'rect', {'rx': 15, 'ry': 15, 'x': 0, 'y': 0, 'width': 84, 'height': 34, 'fill': '#A8A9A8'});
|
||||||
pxsim.svg.child(this.syncedLabelG, 'circle', {'cx': 17, 'cy': 17, 'r': 15, 'fill': 'white'});
|
pxsim.svg.child(this.syncedLabelG, 'circle', {'cx': 17, 'cy': 17, 'r': 15, 'fill': 'white'});
|
||||||
const leftLabel = pxsim.svg.child(this.syncedLabelG, 'text', {'transform': 'translate(11, 22)', 'style': 'isolation: isolate;font-size: 16px;fill: #A8A9A8;font-family: ArialMT, Arial'});
|
const leftLabel = pxsim.svg.child(this.syncedLabelG, 'text', {'transform': 'translate(11, 22)', 'class': 'no-drag', 'style': 'isolation: isolate;font-size: 16px;fill: #A8A9A8;font-family: ArialMT, Arial'});
|
||||||
leftLabel.textContent = a;
|
leftLabel.textContent = a;
|
||||||
|
|
||||||
pxsim.svg.child(this.syncedLabelG, 'rect', {'rx': 0, 'ry': 0, 'x': 37, 'y': 12, 'width': 10, 'height': 3, 'fill': '#ffffff'});
|
pxsim.svg.child(this.syncedLabelG, 'rect', {'rx': 0, 'ry': 0, 'x': 37, 'y': 12, 'width': 10, 'height': 3, 'fill': '#ffffff'});
|
||||||
pxsim.svg.child(this.syncedLabelG, 'rect', {'rx': 0, 'ry': 0, 'x': 37, 'y': 18, 'width': 10, 'height': 3, 'fill': '#ffffff'});
|
pxsim.svg.child(this.syncedLabelG, 'rect', {'rx': 0, 'ry': 0, 'x': 37, 'y': 18, 'width': 10, 'height': 3, 'fill': '#ffffff'});
|
||||||
|
|
||||||
pxsim.svg.child(this.syncedLabelG, 'circle', {'cx': 67, 'cy': 17, 'r': 15, 'fill': 'white'});
|
pxsim.svg.child(this.syncedLabelG, 'circle', {'cx': 67, 'cy': 17, 'r': 15, 'fill': 'white'});
|
||||||
const rightLabel = pxsim.svg.child(this.syncedLabelG, 'text', {'transform': 'translate(61, 22)', 'style': 'isolation: isolate;font-size: 16px;fill: #A8A9A8;font-family: ArialMT, Arial'});
|
const rightLabel = pxsim.svg.child(this.syncedLabelG, 'text', {'transform': 'translate(61, 22)', 'class': 'no-drag', 'style': 'isolation: isolate;font-size: 16px;fill: #A8A9A8;font-family: ArialMT, Arial'});
|
||||||
rightLabel.textContent = b;
|
rightLabel.textContent = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected renderMotorAngle(holeEl: Element, angle: number) {
|
protected renderMotorAngle(holeEl: Element, angle: number) {
|
||||||
const width = 125.92;
|
const width = 35.92;
|
||||||
const height = 37.9;
|
const height = 35.9;
|
||||||
const transform = `rotate(${angle} ${width / 2} ${height / 2})`;
|
const transform = `translate(45.000000, 1.000000) rotate(${angle} ${width / 2} ${height / 2})`;
|
||||||
holeEl.setAttribute("transform", transform);
|
holeEl.setAttribute("transform", transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.blocklyFlyoutLabel .blocklyFlyoutLabelIcon {
|
.blocklyFlyoutLabel .blocklyFlyoutLabelIcon {
|
||||||
font-family: 'legoIcons';
|
font-family: 'legoIcons' !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.blocklyTreeIcon {
|
span.blocklyTreeIcon {
|
||||||
|
Reference in New Issue
Block a user