View difference between Paste ID: tpmh18dR and Gy60HJLV
SHOW: | | - or go back to the newest paste.
1
-- Goto
2-
-- by SukkaiPoppuGo
2+
3
4
assert(pocket, "Require pocket computer")
5
6-
local target = vector.new(-100, 50, -25)
6+
local target = {name="Origin",x=0,y=0,z=0}
7
local playerData = pocket.getEntity()
8
local player = vector.new( playerData.x, playerData.y, playerData.z )
9
10-
--https://math.stackexchange.com/questions/42640/calculate-distance-in-3d-space
10+
11-
function distance(A, B)
11+
12-
    return math.sqrt(math.pow(B.x - A.x, 2) + math.pow(B.y - A.y, 2) + math.pow(B.z - A.z, 2))
12+
13
local screenW, screenH = 26, 20
14
15
------------------------
16
-- API Mgr
17
--
18
-- Wizard
19
local function wizard(api, name, code, path)
20-
    local angle = math.rad(-yaw % 360)
20+
	if not api then
21-
    local px = math.cos(angle) * -x - math.sin(angle) * -z
21+
		local confirm
22-
    local py = math.sin(angle) * -x + math.cos(angle) * -z
22+
		repeat
23-
    return px, py
23+
			print(name,"API required")
24
			print("pastebin get", code, path)
25
			print("Download ? Y/N")
26
			confirm = string.lower(read())
27-
    return B - A
27+
			if confirm ~= "y" and confirm ~= "n" then
28
				printError(confirm, "Invalid\n")
29
			end
30
		until confirm == "y" or confirm == "n"
31
		if confirm == "y" then
32
			shell.run("pastebin get", code, path)
33
			sleep(1)
34
			if not os.loadAPI(path) then
35
				printError("Setup failed..")
36
			end
37-
-- Pixel API Wizard
37+
38
			print("Abort")
39-
if not pixel then
39+
			return
40-
	local confirm
40+
41-
	repeat
41+
42-
		print("Pixel API required")
42+
43-
		print("pastebin get Fa9KJqS4 /api/pixel.lua")
43+
-- Load APIs
44-
		print("Download ? Y/N")
44+
os.loadAPI("/api/utils.lua")
45-
		confirm = string.lower(read())
45+
wizard(utils, "Utils", "ng7cqnjg", "/api/utils.lua")
46-
		if confirm ~= "y" and confirm ~= "n" then
46+
assert(utils, "Utils API required\npastebin get ng7cqnjg /api/utils.lua")
47-
			printError(confirm, "Invalid\n")
47+
os.loadAPI("/api/ui.lua")
48
wizard(utils, "UI", "ipGrW02P", "/api/ui.lua")
49-
	until confirm == "y" or confirm == "n"
49+
assert(utils, "Utils API required\npastebin get ipGrW02P /api/ui.lua")
50-
	if confirm == "y" then
50+
51-
		shell.run("pastebin get Fa9KJqS4 /api/pixel.lua")
51+
wizard(pixel, "Pixel", "Fa9KJqS4", "/api/pixel.lua")
52-
		sleep(1)
52+
assert(pixel, "Pixel API required\npastebin get Fa9KJqS4 /api/pixel.lua")
53-
		os.loadAPI("/api/pixel.lua")
53+
os.loadAPI("/api/numbers.lua")
54-
		if not pixel then
54+
wizard(numbers, "Numbers", "e0k0ZVQy", "/api/numbers.lua")
55-
			printError("Setup failed..")
55+
assert(numbers, "Numbers API required\npastebin get e0k0ZVQy /api/numbers.lua")
56
57
------------------------
58-
		print("Abort")
58+
-- UTILS
59
local function isColinear( A, B )
60
   return A.x * B.z == B.x * A.z
61
end
62-
-- End Wizard
62+
63
local function convertXZToScreen(x, z, yaw)
64
	local angle = math.rad(-yaw % 360)
65
	local px = math.cos(angle) * -x - math.sin(angle) * -z
66
	local py = math.sin(angle) * -x + math.cos(angle) * -z
67-
-- Native char pixel: 26 x 20 borderless ------------------->  88 outline borderless
67+
	return px, py
68-
-- With pixel API   : 26 x 30 borderless -> 24 x 28 framed -> 108 outline borderless -> 100 outline framed
68+
69-
-- With blittle API : 52 x 60 borderless -> 48 x 54 framed -> 220 outline borderless -> 200 outline framed
69+
70
local function abs2rel(A, B)
71-
local _n = {
71+
	local a,b = vector.new(A.x,A.y,A.z), vector.new(B.x,B.y,B.z)
72-
{"000","ff0","000","000","0f0","000","000","000","000","000",},
72+
	return b - a
73-
{"0f0","ff0","ff0","ff0","0f0","0ff","0ff","ff0","0f0","0f0",},
73+
74-
{"0f0","ff0","000","000","000","000","000","ff0","000","000",},
74+
75-
{"0f0","ff0","0ff","ff0","ff0","ff0","0f0","ff0","0f0","ff0",},
75+
76-
{"000","ff0","000","000","ff0","000","000","ff0","000","000",},
76+
77
------------------------
78-
local tNum = {}
78+
-- DEBUG
79-
for i=0,9 do
79+
local _debug = {}
80-
	tNum[i] = pixel.compute({_n[1][i],_n[2][i],_n[3][i],_n[4][i],_n[5][i]})
80+
_debug.visible = false
81
local function debugPXPY(px,py)
82
	if _debug.visible then
83-
function test()
83+
		term.setCursorPos(1,19)
84
		term.clearLine()
85-
	local x,y = 4,6
85+
		term.write(string.format("x: %s, y: %s", px, py))
86-
	for i=0,9 do
86+
87-
		term.setCursorPos(x + ((i%5)*4), i > 4 and y+6 or y)
87+
88-
		pixel.draw(tNum[i])
88+
local function debugMaxMinPXPY(px,py)
89
	if not _debug.pxpy then
90-
	term.setCursorPos(3,18)
90+
		_debug.pxpy = {
91-
	read()
91+
			maxPX = 0, maxPY = 0,
92
			minPX = math.huge, minPY = math.huge,
93
		}
94
	end
95
	_debug.pxpy.maxPX = math.max(px,_debug.pxpy.maxPX)
96
	_debug.pxpy.maxPY = math.max(py,_debug.pxpy.maxPY)
97-
	assert(string.len(tostring(num)) <= 6, string.format([[! "%s" too long (5 digits)]], num))
97+
	_debug.pxpy.minPX = math.min(px,_debug.pxpy.minPX)
98
	_debug.pxpy.minPY = math.min(py,_debug.pxpy.minPY)
99-
	--debug
99+
100-
	term.setCursorPos(1,y < 10 and 2 or 17)
100+
	if _debug.visible then
101-
	term.clearLine()
101+
		term.setCursorPos(1,20)
102-
	print("num:", num, "s:", tostring(num), "n:", tonumber(num))
102+
		term.clearLine()
103-
	term.setCursorPos(1,y < 10 and 3 or 18)
103+
		term.write(string.format(
104-
	term.clearLine()
104+
			"X: %s~%s Y: %s~%s",
105-
	term.write("split: ")
105+
			math.floor(_debug.pxpy.minPX*10)/10, math.floor(_debug.pxpy.maxPX*10)/10,
106
			math.floor(_debug.pxpy.minPY*10)/10, math.floor(_debug.pxpy.maxPY*10)/10
107-
	local line = {"","","","",""}
107+
		))
108-
	for i=1,string.len(num) do
108+
109-
		if string.sub(num,i,i) == " " then
109+
110-
			local pad = i == string.len(num) and "" or " "
110+
local function debugDisplay(num, x, y)
111-
			line[1] = line[1].." "..pad
111+
	if _debug.visible then
112-
			line[2] = line[2].." "..pad
112+
		term.setCursorPos(1,y < 10 and 2 or 17)
113-
			line[3] = line[3].." "..pad
113+
		term.clearLine()
114-
			line[4] = line[4].." "..pad
114+
		print("num:", num, "s:", tostring(num), "n:", tonumber(num))
115-
			line[5] = line[5].." "..pad
115+
		term.setCursorPos(1,y < 10 and 3 or 18)
116-
		elseif i == 1 and tonumber(num) < 0 then --nombre négatif
116+
		term.clearLine()
117-
			line = string.len(num) == maxLen and {" ff "," ff "," 00 "," ff "," ff "} or {"fff ","fff ","000 ","fff ","fff "}
117+
		term.write("split: ")
118-
			term.write("-")
118+
119
end
120-
			term.write(tonumber(string.sub(num,i,i)).." ")
120+
121-
			local n = tonumber(string.sub(num,i,i))
121+
122-
			local pad = i == string.len(num) and "" or " "
122+
123-
			line[1] = line[1].._n[1][n+1]..pad
123+
124-
			line[2] = line[2].._n[2][n+1]..pad
124+
local function minus(sp)
125-
			line[3] = line[3].._n[3][n+1]..pad
125+
	sp = sp or ""
126-
			line[4] = line[4].._n[4][n+1]..pad
126+
	return {
127-
			line[5] = line[5].._n[5][n+1]..pad
127+
		{" "..sp,    "0"..sp, "f"..sp},
128
		{"\140"..sp, "0"..sp, "f"..sp},
129
		{" "..sp,    "0"..sp, "f"..sp},
130
	}
131-
	pixel.draw(pixel.compute(line))
131+
132
133
local maxLen = 6
134-
function alignLeft()
134+
135
	assert(tonumber(num), string.format([[! "%s" NaN]], num))
136
	if string.len(tostring(num)) > 6 then --too long
137
		term.setCursorPos(2, y)
138
		print(num)
139
		return
140
	end
141
	
142
	debugDisplay(num, x, y)
143
	
144
	num = string.sub(tostring(num)..string.rep(" ",maxLen),1,maxLen)
145
	term.setCursorPos(x, y)
146-
local maxPX,maxPY,minPX,minPY = 0,0,math.huge,math.huge
146+
	local line = {"","",""}
147
	for cx=1,string.len(num) do
148-
local w,h = term.getSize()
148+
		if string.sub(num,cx,cx) == " " then
149-
local function screenConv(px,py, dist)
149+
			local pad = cx == string.len(num) and "" or " "
150-
    
150+
			for cy=1, 3 do
151-
    local _x = math.min(w,math.max(1,math.floor(px+(dist/2)*w/dist)))
151+
				term.setCursorPos(x + ((cx-1)*4), y + cy -1)
152-
    local _y = math.min(h,math.max(1,math.floor(py+(dist/2)*h/dist)))
152+
				term.write(" "..pad)
153-
    term.setCursorPos(_x,_y)
153+
			end
154-
    term.blit("\7","5","f")
154+
		elseif cx == 1 and tonumber(num) < 0 then --nombre négatif
155
			for cy,c in ipairs(minus(string.len(num) == maxLen and " " or "")) do
156
				term.setCursorPos(x + ((cx-1)*4), y + cy -1)
157-
target = vector.new(-4989,50,-2564)
157+
				term.blit(unpack(c))
158
			end
159-
    local px,py = convertXZToScreen(target.x-p.x, target.z-p.z, p.yaw)
159+
160-
    term.setCursorPos(1,1)
160+
			local pad = cx == string.len(num) and {"","",""} or {"f","f","f"}
161-
    term.write(string.format("x: %s, y: %s",px,py))
161+
			for cy,c in ipairs(numbers.get(tonumber(string.sub(num,cx,cx)))) do
162-
    
162+
				term.setCursorPos(x + ((cx-1)*4), y + cy -1)
163-
    maxPX = math.max(px,maxPX)
163+
				term.blit(c[1]..pad[1], c[2]..pad[2], c[3]..pad[3])
164-
    maxPY = math.max(py,maxPY)
164+
			end
165-
    minPX = math.min(px,minPX)
165+
166-
    minPY = math.min(py,minPY)
166+
167-
    term.setCursorPos(1,20)
167+
168-
    term.write(string.format(
168+
169-
        "X: %s~%s Y: %s~%s",
169+
-------------------
170-
        math.floor(minPX*10)/10, math.floor(maxPX*10)/10,
170+
-- Aligns modes (return left margin width)
171-
        math.floor(minPY*10)/10, math.floor(maxPY*10)/10
171+
function alignLeft(v, margin)
172-
    ))
172+
173-
    screenConv(px,py, distance(target,p))
173+
174
function alignCenter(v)
175
	local w = string.len(tostring(v))*4
176
	return math.floor((screenW - w) / 2)
177-
while true do
177+
178
function alignRight(v, margin)
179
	local w = string.len(tostring(v))*4
180-
	term.setTextColor(colors.gray)
180+
181-
	display(math.floor(p.x), alignCenter(math.floor(p.x), 4), 6)
181+
182-
	display(math.floor(p.z), alignCenter(math.floor(p.z), 4), 12)
182+
183
-------------------
184-
 term.setCursorPos(1,19)
184+
-- Compas cursor
185-
 term.write("Distance: "..distance(target,p))
185+
186
	local rel = abs2rel(target, p)
187-
 cursor(p)
187+
	local px, py = convertXZToScreen(rel.x, rel.z, p.yaw)
188-
	sleep(.1)
188+
189-
end
189+
	debugPXPY(px, py)
190
	debugMaxMinPXPY(px, py)
191
	
192
	local dist = math.sqrt(rel.x^2 + rel.z^2) --plane distance (2D)
193
	local dist_half = dist/2
194
	local _x = utils.constraint(math.round((-px + dist_half) * screenW / dist), 1, screenW)
195
	local _y = utils.constraint(math.round((-py + dist_half) * screenH / dist), 1, screenH)
196
	
197
	for cy=-1,0,1 do
198
		term.setCursorPos(_x-1,_y + cy)
199
		term.blit("   ","fff","555") --term.blit("\7","5","f")
200
	end
201
end
202
203
-------------------
204
-- Toggleable standard output
205
local output = window.create(term.current(), 2,14, 22,5, false)
206
output.visible = false
207
function output.print(...)
208
	local x,y = term.getCursorPos()
209
	local old = term.redirect(output)
210
	print(...)
211
	term.redirect(old)
212
	term.setCursorPos(x,y)
213
end
214
215
-------------------
216
-- About
217
local Skypop = window.create(term.current(), 2,15, 22,4, false)
218
local nativePink = {term.getPaletteColor( colors.pink )}
219
Skypop.setPaletteColor(colors.pink, 215/255, 138/255, 127/255)
220
Skypop.visible = false
221
for _y,_line in ipairs({
222
  { "\159\143\143\143\144", "ffff6", "6666f" },
223
  { "\149\151 \148\149",    "f00f6", "6f60f" },
224
  { "\149\136\143\132\149", "ff6f6", "66f6f" },
225
  { "\130\131\131\131\129", "66666", "fffff" },
226
}) do
227
    Skypop.setCursorPos(1, _y)
228
    Skypop.blit(unpack(_line))
229
end
230
Skypop.setCursorPos(6, 2)
231
Skypop.write(fs.getName(shell.getRunningProgram()))
232
Skypop.setCursorPos(6, 3)
233
Skypop.write("by SukaiPoppuGo")
234
term.setPaletteColor(colors.pink, unpack(nativePink))
235
236
-------------------
237
-- Waypoint list
238
local waypoints = window.create(term.current(), 2,3, 22,15, false)
239
waypoints.visible = false
240
waypoints.width, waypoints.height = waypoints.getSize()
241
242
-- Reload
243
settings.load(".settings")
244
waypoints.data = settings.get("waypoints.data", {})
245
-- List selected item
246
waypoints.selection = settings.get("waypoints.selection", 0)
247
if waypoints.data[waypoints.selection]
248
and vector.new(
249
	waypoints.data[waypoints.selection].x,
250
	waypoints.data[waypoints.selection].y,
251
	waypoints.data[waypoints.selection].z
252
) then
253
	target = waypoints.data[waypoints.selection]
254
end
255
-- List position display
256
waypoints.index = settings.get("waypoints.index", 1)
257
258
function waypoints.emptyList() return {"","","","","","","","","","","",""} end
259
function waypoints.list()
260
	ui.box({waypoints.menu, unpack(waypoints.emptyList())}, waypoints.width, "Waypoints", waypoints)
261
	local y=3
262
	for i=waypoints.index, waypoints.index + waypoints.height-4 do
263
		if waypoints.data[i] then
264
			local wp = waypoints.data[i]
265
			--Selected item
266
			if i == waypoints.selection then
267
				waypoints.setTextColor(colors.yellow)
268
			end
269
			local line = string.sub(wp.name..string.rep(" ",waypoints.width),0,waypoints.width-4).."[\215"
270
			waypoints.setCursorPos(2,y)
271
			waypoints.write(line)
272
			waypoints.setTextColor(colors.white)
273
		end
274
		y = y+1
275
	end
276
end
277
278
waypoints.form = window.create(waypoints, 1,1, waypoints.width, waypoints.height, false)
279
280
-- Update list
281
function waypoints.update(e)
282
	if waypoints.visible then
283
		--Params
284
		local height = waypoints.height-3
285
		local x,y = waypoints.getPosition()
286
		
287
		-- List scrolling
288
		if e[1] == "mouse_scroll" then
289
			output.print(" List scrolling")
290
			
291
			--List constraint
292
			waypoints.index = math.max(waypoints.index + e[2], 1)
293
			waypoints.index = math.min(waypoints.index, #waypoints.data)
294
		
295
		-- Add waypoint
296
		elseif e[1] == "mouse_click"
297
		and e[2] == 1
298
		and e[3] >= x and e[3] <= x + waypoints.width
299
		and e[4] == y+1
300
		then
301
			output.print(" Add waypoint")
302
			
303
			waypoints.form.clear()
304
			waypoints.form.setCursorPos(1,1)
305
			ui.box({"Name:","","X:","Y:","Z:",""},waypoints.width-2,"New waypoint", waypoints.form)
306
			waypoints.form.setVisible(true)
307
			waypoints.form.redraw()
308
			local wp = {}
309
			--input name
310
			waypoints.form.setCursorPos(2,3)
311
			wp.name = tostring(read())
312
			--input coords
313
			waypoints.form.setCursorPos(5,4)
314
			wp.x = tonumber(read())
315
			waypoints.form.setCursorPos(5,5)
316
			wp.y = tonumber(read())
317
			waypoints.form.setCursorPos(5,6)
318
			wp.z = tonumber(read())
319
			if vector.new(wp.x, wp.y, wp.z) then
320
				table.insert(waypoints.data, wp)
321
				settings.set("waypoints.data", waypoints.data)
322
				settings.save(".settings")
323
				waypoints.form.setCursorPos(2,7)
324
				waypoints.form.write("Saved, press any key")
325
				--waypoints.form.redraw()
326
				ui.waitPressAnyKey()
327
			else
328
				waypoints.form.setCursorPos(2,7)
329
				waypoints.form.write("Coords error")
330
				--waypoints.form.redraw()
331
				ui.waitPressAnyKey()
332
			end
333
			sleep(1)
334
			waypoints.form.clear()
335
			waypoints.form.setVisible(false)
336
			waypoints.form.redraw()
337
			waypoints.setVisible(true)
338
			waypoints.visible = true
339
			waypoints.redraw()
340
			
341
		-- Delete waypoint
342
		elseif e[1] == "mouse_click"
343
		and e[2] == 1
344
		and e[3] == x + waypoints.width -2
345
		and e[4] >= y+2 and e[4] <=  y + height + 1
346
		and waypoints.data[e[4] - (y+2) + waypoints.index]
347
		then
348
			output.print(" Delete waypoint")
349
			table.remove(waypoints.data, e[4] - (y+2) + waypoints.index)
350
			settings.set("waypoints.data", waypoints.data)
351
			settings.save(".settings")
352
			waypoints.setCursorPos(2, e[4] - y +1)
353
			waypoints.write("deleted             ")
354
			waypoints.redraw()
355
			sleep(1)
356
			
357
		-- Select waypoint
358
		elseif e[1] == "mouse_click"
359
		and e[2] == 1
360
		and e[3] >= x and e[3] <= x + waypoints.width-3
361
		and e[4] >= y+2 and e[4] <= y + height + 1
362
		then
363
			output.print(" Select waypoint")
364
			
365
			local selection = e[4] - (y+2) + waypoints.index
366
			if waypoints.data[selection] then
367
				waypoints.selection = selection
368
				settings.set("waypoints.selection", selection)
369
				settings.set("waypoints.index", waypoints.index)
370
				settings.save(".settings")
371
				target = waypoints.data[selection]
372
			end
373
		end
374
	end
375
	--Init display
376
	waypoints.setCursorPos(1,1)
377
	waypoints.clear()
378
	ui.box({
379
			string.format(
380
				"<New point> (%s/%s)",
381
				#waypoints.data == 0 and 0 or waypoints.index,
382
				#waypoints.data
383
			),
384
			unpack(waypoints.emptyList())
385
		},
386
		waypoints.width,
387
		"Waypoints",
388
		waypoints
389
	)
390
	waypoints.list()
391
	waypoints.redraw()
392
end
393
394
395
-------------------
396
-- Menu bar
397
local menu = window.create(term.current(), 2,19, 22,1, true)
398
local items = {
399
	{
400
		name = "\2",
401
		clicked = false,
402
		action = function()
403
			Skypop.visible = not Skypop.visible --toggle display state
404
			Skypop.setVisible(Skypop.visible)
405
			Skypop.redraw()
406
		end,
407
	},
408
	{
409
		name = "List",
410
		clicked = false,
411
		action = function()
412
			waypoints.visible = not waypoints.visible --toggle display state
413
			waypoints.setVisible(waypoints.visible)
414
			waypoints.redraw()
415
		end,
416
	},
417
	{
418
		name = "Output",
419
		clicked = false,
420
		action = function()
421
			output.visible = not output.visible --toggle display state
422
			output.setVisible(output.visible)
423
			output.redraw()
424
		end,
425
	},
426
	{
427
		name = "Exit",
428
		clicked = false,
429
		action = function()
430
			os.queueEvent("terminate")
431
		end,
432
	}
433
}
434
function menu.update(e)
435
	
436
	local x,y = term.getCursorPos()
437
	
438
	-- Handle mouse_click
439
	local _x,_y = menu.getPosition()
440
	local cx = 1
441
	if e and e[1] == "mouse_click" and e[2] == 1 and e[4] == _y then
442
		for i,item in ipairs(items) do
443
			local x1, x2 = cx, cx + string.len(item.name) +1
444
			items[i].clicked = (e[3] >= x1 and e[3] <= x2)
445
			cx = x2+1
446
		end
447
	elseif e and e[1] == "mouse_up" then
448
		for i,item in ipairs(items) do
449
			local x1, x2 = cx, cx + string.len(item.name) +1
450
			if items[i].clicked
451
			and e[3] >= x1 and e[3] <= x2
452
			and e[2] == 1 and e[4] == _y
453
			and type(items[i].action) == "function" then
454
				if _debug.visible then
455
					term.setCursorPos(2,2)
456
					print(items[i].name, "click")
457
					sleep(.3)
458
				end
459
				items[i].action()
460
			end
461
			cx = x2+1
462
			items[i].clicked = false
463
		end
464
	end
465
	
466
	menu.setCursorPos(1,1)
467
	menu.clearLine()
468
	for i,item in ipairs(items) do
469
		ui.btn(item.name, item.clicked, menu)
470
	end
471
	menu.redraw()
472
	
473
	term.setCursorPos(x,y)
474
end
475
476
-------------------
477
-- Main loop
478
local e = nil
479
repeat
480
	local p = pocket.getEntity()
481
	term.clear()
482
	
483
	menu.update(e)
484
	
485
	if waypoints.visible then
486
		waypoints.update(e)
487
	else
488
		local dist = math.floor(utils.distance(target,p))
489
		term.setTextColor(colors.lightGray)
490
		term.setCursorPos(3,4)
491
		term.write("Target: "..target.name)
492
		term.setCursorPos(3,5)
493
		local strPos = string.format("x:%s, y:%s, z:%s", target.x, target.y, target.z)
494
		print(strPos)
495
		local x,y = term.getCursorPos()
496
		term.setCursorPos(3,y)
497
		term.write("Distance:")
498
		display(dist, alignCenter(dist, 4), y+1)
499
		cursor(p)
500
	end
501
	
502
	Skypop.redraw()
503
	
504
	--PLayer coordinates
505
	term.setTextColor(colors.lightGray)
506
	term.setCursorPos(2,2)
507
	term.write("Pos: "..math.floor(p.x)..","..math.floor(p.y)..","..math.floor(p.z)) -- distance 3D
508
	
509
	output.redraw()
510
 
511
	local tick = os.startTimer(0.1)
512
	e = {os.pullEventRaw()}
513
	os.cancelTimer(tick)
514
	--trace events
515
	if not (e[1] == "timer" and e[2] == tick) then
516
		output.print(unpack(e))
517
	end
518
	
519
until e[1] == "terminate"
520
term.setCursorPos(1,1)
521
term.clear()
522
printError("Terminated")