This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

[SOLVED]|shift| and program overload

Started by KingofGamesYami, 18 April 2014 - 02:41 PM
KingofGamesYami #1
Posted 18 April 2014 - 04:41 PM
For some reason, when I press |shift| on screen, my program simply doesn't work anymore. It continues to loop, but doesn't appear to get any monitor_touch events. Also, I can break the program simply by clicking on the monitor rapidly. Is there anyway to fix this?

Spoiler

local mon = peripheral.wrap("right")
local dmon = peripheral.wrap("monitor_4")
local i, input, shift, touch = 0, "string", "False", {}
local ln1, ln2, ln3, ln4 = "string", "string", "string", "string"

dmon.setTextScale(3)
mon.setTextScale(4)
mon.setBackgroundColor(colors.blue)
mon.clear()

while true do
--Check shift
if shift == "True" then
  ln1, ln2, ln3, ln4 = "!@#$%^&*()  |DELETE|", " QWERTYUIOP", "  ASDFGHJKL  |ENTER|", "   ZXCVBNM   |SHIFT|"
  shift = "False"
elseif shift == "False" then
  ln1, ln2, ln3, ln4 = "1234567890  |delete|", " qwertyuiop", "  asdfghjkl  |enter|", "   zxcvbnm   |shift|"
end
--Render
mon.clear()
mon.setCursorPos(1, 1) mon.write(ln1)
mon.setCursorPos(1, 2) mon.write(ln2)
mon.setCursorPos(1, 3) mon.write(ln3)
mon.setCursorPos(1, 4) mon.write(ln4)

  i = #touch + 1 --#Changed this from "i = i + 1" and it works now...
  local event, side, x, y = os.pullEvent("monitor_touch")
  if y == 1 and x <= 10 then
   touch[i] = string.sub(ln1, x, x)
  elseif y == 2 and x <= 11 then
   touch[i] = string.sub(ln2, x, x)
  elseif y == 3 and x <= 11 then
   touch[i] = string.sub(ln3, x, x)
  elseif y == 4 and x <= 10 then
   touch[i] = string.sub(ln4, x, x)
  elseif y == 1 and x >= 13 and x <= 20 then --Delete Button
   i = #touch - 1
   touch[#touch] = nil
  elseif y == 3 and x >= 14 and x <= 20 then  --Enter Button
   input = table.concat(touch)
	if input == "Pa55w0rd" then --commands here
	 rednet.open("left")
	 rednet.broadcast("Success!")
	 rednet.close("left")
	end
   touch, i = {}, 0
  elseif y == 4 and x >= 14 and x <= 20 then --Shift Button
   if shift == "True" then
	shift = "False"
   else
	shift = "True"
   end
  end
  dmon.clear()
  dmon.setCursorPos(1, 2)
  if table.concat(touch) then
   dmon.write(table.concat(touch))
  end
  sleep(0.1)
end

Edit: Fixed the overload problem, but shift still glitches.
Edit2: forgot to say, this program should work as a keyboard now :P/>
Edited on 19 April 2014 - 12:20 AM
Bomb Bloke #2
Posted 19 April 2014 - 02:12 AM
That's an interesting way of handling "booleans"…

I can't see anything in there that'd stop it from picking up touch events. That sleep statement near the bottom may prevent it from picking up some, but certainly not most, let alone all.

One thing that might be a bit confusing is that you disable shift when you draw the upper case characters. This makes it impossible to turn shift "off" by clicking the shift button, as it's already disabled by that point.
KingofGamesYami #3
Posted 19 April 2014 - 02:16 AM
That's an interesting way of handling "booleans"…

I can't see anything in there that'd stop it from picking up touch events. That sleep statement near the bottom may prevent it from picking up some, but certainly not most, let alone all.

One thing that might be a bit confusing is that you disable shift when you draw the upper case characters. This makes it impossible to turn shift "off" by clicking the shift button, as it's already disabled by that point.
Actually, shift does NOT disable/enable as a button, "shift" is simply the variable that determines whether the strings are uppercase or lowercase. The button is ALWAYS active. Plus, the idea was to make it as close to actual Shift rather than Caps Lock. (originally it was basically Caps Lock)

The problem was, when I clicked shift the program would run and I would have something like this:
touch[1] = "h"
–*presses shift*
touch[3] = "_"
It would then error because touch[2] isn't defined. edit: I think. I don't know why the fix (i = i +1 i = #touch + 1) worked, but it did. Also, the touch_events not being picked up was due to my game lagging (I think)
Edited on 19 April 2014 - 12:28 AM
Bomb Bloke #4
Posted 19 April 2014 - 02:18 AM
Ok. So what's your current problem with it?
KingofGamesYami #5
Posted 19 April 2014 - 02:29 AM
Ok. So what's your current problem with it?
There is none. I marked it as [SOLVED] didn't I? I fixed both problems I originally posted about (took me about three hours to figure out, but I did)
theoriginalbit #6
Posted 19 April 2014 - 02:46 AM
As a point of learning I've made some improvements for you and commented them, if you have any questions about anything in the code feel free to ask them

local mon = peripheral.wrap("right")
local dmon = peripheral.wrap("monitor_4")

--# we can use an empty string for input, no need to use a table to then put it in the input
--# we can also use booleans, instead of a string 'True' and 'False'
local input, shiftPressed = "", false

--# a table containing the possible keyboard inputs
local keyboard = {
  --# the table key is the shift state, yes we can use booleans as keys in tables!
  [true] = { "!@#$%^&amp;*()  |delete|"," QWERTYUIOP","  ASDFGHJKL  |enter|","   ZXCVBNM   |shift|"},
  [false] = {"1234567890  |delete|"," qwertyuiop","  asdfghjkl  |enter|","   zxcvbnm   |shift|"}
}

dmon.setTextScale(3)
mon.setTextScale(4)
mon.setBackgroundColor(colors.blue)
mon.clear()

while true do
  --# render, we don't need to clear as the lines are the same length so will override previous
  for i = 1, 4 do
    mon.setCursorPos(1, i)
    --# lookup the keyboard with the shift state and line
    mon.write(keyboard[shiftPressed][i])
  end

  --# wait for input
  local event, side, x, y = os.pullEvent("monitor_touch")

  --# all keyboard characters end before any button, meaning we can use the following logic
  if x <= 11 and y <= 4 then
    --# look up the keyboard character based on shift state, the y position, and the x position
    local char = string.sub(keyboard[shiftPressed][y], x, x)
    --# if there was a character at that possition
    if char ~= ' ' then
      --# append the character to the input
      input = input..char
    end

  --# Delete Button
  elseif y == 1 and x >= 13 and x <= 20 then
    --# remove the last char
    input = input:sub(1, #input-1)

  --# the click was at the position of enter or shift
  elseif x >= 14 and x <= 20 then
    --# enter button
    if y == 3 then
      if input == "Pa55w0rd" then
        rednet.open("left")
        rednet.broadcast("Success!")
        rednet.close("left")
      end
      input = "" --# reset the input

    --# shift button
    elseif y == 4 then
      shiftPressed = not shiftPressed --# invert the shiftPressed 'not true == false', 'not false == true'
    end
  end
  dmon.clear()
  dmon.setCursorPos(1, 2)
  dmon.write(input)
  --# removed the sleep, it means you can miss monitor touches
end
Edited on 19 April 2014 - 12:47 AM
KingofGamesYami #7
Posted 19 April 2014 - 04:31 AM
As a point of learning I've made some improvements for you and commented them, if you have any questions about anything in the code feel free to ask them

local mon = peripheral.wrap("right")
local dmon = peripheral.wrap("monitor_4")

--# we can use an empty string for input, no need to use a table to then put it in the input
--# we can also use booleans, instead of a string 'True' and 'False'
local input, shiftPressed = "", false

--# a table containing the possible keyboard inputs
local keyboard = {
  --# the table key is the shift state, yes we can use booleans as keys in tables!
  [true] = { "!@#$%^&amp;*()  |delete|"," QWERTYUIOP","  ASDFGHJKL  |enter|","   ZXCVBNM   |shift|"},
  [false] = {"1234567890  |delete|"," qwertyuiop","  asdfghjkl  |enter|","   zxcvbnm   |shift|"}
}

dmon.setTextScale(3)
mon.setTextScale(4)
mon.setBackgroundColor(colors.blue)
mon.clear()

while true do
  --# render, we don't need to clear as the lines are the same length so will override previous
  for i = 1, 4 do
    mon.setCursorPos(1, i)
    --# lookup the keyboard with the shift state and line
    mon.write(keyboard[shiftPressed][i])
  end

  --# wait for input
  local event, side, x, y = os.pullEvent("monitor_touch")

  --# all keyboard characters end before any button, meaning we can use the following logic
  if x <= 11 and y <= 4 then
    --# look up the keyboard character based on shift state, the y position, and the x position
    local char = string.sub(keyboard[shiftPressed][y], x, x)
    --# if there was a character at that possition
    if char ~= ' ' then
      --# append the character to the input
      input = input..char
    end

  --# Delete Button
  elseif y == 1 and x >= 13 and x <= 20 then
    --# remove the last char
    input = input:sub(1, #input-1)

  --# the click was at the position of enter or shift
  elseif x >= 14 and x <= 20 then
    --# enter button
    if y == 3 then
      if input == "Pa55w0rd" then
        rednet.open("left")
        rednet.broadcast("Success!")
        rednet.close("left")
      end
      input = "" --# reset the input

    --# shift button
    elseif y == 4 then
      shiftPressed = not shiftPressed --# invert the shiftPressed 'not true == false', 'not false == true'
    end
  end
  dmon.clear()
  dmon.setCursorPos(1, 2)
  dmon.write(input)
  --# removed the sleep, it means you can miss monitor touches
end
Thanks! I understand what everything does, but I might keep a small sleep (0.01) just to prevent a possible bug(eg. multiple people clicking rapidly) from overloading the computer. I actually did manage to do that once or twice.
theoriginalbit #8
Posted 19 April 2014 - 04:33 AM
I might keep a small sleep (0.01) just to prevent a possible bug(eg. multiple people clicking rapidly) from overloading the computer. I actually did manage to do that once or twice.
:blink:/> overload the computer how? what was the error? :huh:/>
Edited on 19 April 2014 - 02:33 AM
KingofGamesYami #9
Posted 19 April 2014 - 04:45 AM
I might keep a small sleep (0.01) just to prevent a possible bug(eg. multiple people clicking rapidly) from overloading the computer. I actually did manage to do that once or twice.
:blink:/>/>/> overload the computer how? what was the error? :huh:/>/>/>
There wasn't an error, it just stopped running the program.
console looked like this:
>BetaKey
>
So basically it somehow broke the loop. I suspect there is a memory/sec limit on loops or something.
Edit: to replicate…
1) load program onto an advanced comp connected to two advanced monitors (one aprox 4 x 8, the other 1 x 6)
2) while looking at the monitor, hold down right click
3) go look at terminal to see if overloaded
4) if not overloaded, your computer is faster than my macbook! congrats! (can always try with more people)
Edited on 19 April 2014 - 02:57 AM
theoriginalbit #10
Posted 19 April 2014 - 07:28 AM
There wasn't an error, it just stopped running the program.
console looked like this:
>BetaKey
>
So basically it somehow broke the loop. I suspect there is a memory/sec limit on loops or something.
Not possible. You must have killed the loop in some other way, are you using parallel api? or is that all of the code?
Edited on 19 April 2014 - 05:28 AM
KingofGamesYami #11
Posted 19 April 2014 - 11:27 PM
There wasn't an error, it just stopped running the program.
console looked like this:
>BetaKey
>
So basically it somehow broke the loop. I suspect there is a memory/sec limit on loops or something.
Not possible. You must have killed the loop in some other way, are you using parallel api? or is that all of the code?
I never used the parallel api. I actually did it on a previous version of this code, which I don't have anymore (it was the same thing, but didn't include shift plus a lot of stuff was badly written.) It was similar to this:

--#this is not exact, writing from memory
function render()
mon.setCursorPos(1, 1)
mon.write("QWERTYUIOP")
mon.setCursorPos(2, 2)
mon.write("ASDFGHJKL  |SHIFT|")
mon.setCursorPos(3, 3)
mon.write("ZXCVBNM  |ENTER|")
end

function shift()
if shift == true then
  shift = false
else
  shift = true
end
end

random_var, ranodom_var2, x, y = os.pullEvent("monitor_touch")
--#not gonna write out all the if/then statements for the touches, I had actually specified each d*mn letter -_-/>/>
if y == 1 and x == 1 then
  touched[#touched+1] = "A"
elseif --#...


elseif (shift pressed) then --#not going to figure the location out atm
  shift()
end
if shift = true then
  term.write(touched[#touched])
else
  term.write(string.lower(touched[#touched]))
end
shell.run("Key") --loop program by calling itself
Edited on 19 April 2014 - 09:28 PM