Jump to content




Pcutils

utility api

  • You cannot reply to this topic
31 replies to this topic

#1 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 18 September 2013 - 01:00 PM

PCutils by (Mr)robotica34


So, I was trying to test my basic skillz of Lua by writing a computer API, which "helps you do common tasks when making computer programs".

The code itself is pretty simple, but just helps out some simple tasks and avoids typing long and cluttered commands.
The API still lacks some proper functionality and error checking, but I can call this stable. Most of the error-checking is done!

Use of this API:
Spoiler

Pastebin link for the API: http://www.pastebin.com/f1wL29PW

For lazy people out there:
pastebin get f1wL29PW pcapi
Sorry, the code is not commented, but it's simple, so you smart people will understand it =)

I am currently working alone, would appreciate any and all help. I'd also like to learn more in Lua :)

All feedback accepted!


Function list:
Spoiler

FAQ (Frequently Asked Questions):
Spoiler
Changelog:
Spoiler


Update v1.1!

Finally an update, which has improved the code with the help of the amazing community, and added more useful features to the code.

All changes can be seen in the changelog, version 1.1 .


Update v1.2!

A long waited update is now OUT! Shrunk code, improved it, buttons now support text, error messages are more clear now and more! Check the changelog for details.



#2 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 18 September 2013 - 02:11 PM

1. Take a look into pastebin, its good for hosting large code and there is a program included in ComputerCraft to download from pastebin
2. Take a look into parsing the colours so that people can supply strings or the colours themselves, there was a thread in Ask a Pro a month or two back where I helped someone with colour parsing
3. I looked at this when the contents was only testing spoilers, please use the view button next time instead of the post button
4. The editor does that because of how emoticons work. The /> is applied to the emoticon, as well as any appropriate capitalising, like with B), so that it appears as an emoticon in the normal view. The code tags are designed however to show code, not emoticons or any other formatting, but the damage is already done because the parser that adds the /> is not designed to ignore the match if it is inside of code tags. You also get bad code when you attempt to do any other formatting such as colour or size in code tags, try it!

#3 H4X0RZ

  • Members
  • 1,315 posts
  • LocationGermany

Posted 18 September 2013 - 03:34 PM

A little improvement so you don't have to do so much ifs:
local validColors = {["black"] = colors.black, ["white"] = colors.white} --Expand the table to all colors, this kust an example
local function isValidColor(col)
  if validColors[col:lower()] then --check if its a valid number
    return true --return true if its a valid number
  else
    return false --return false if it isnt a valid color
  end
end

function setBC(col)
  if isValidColor(col) then --if col is a valid color
    term.setBackgroundColor(validColors[col:lower()]
  else
    error("not a valid color!",0)
  end
end
I hope you understand it


#4 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 18 September 2013 - 03:44 PM

View PostFreack100, on 18 September 2013 - 03:34 PM, said:

A little improvement so you don't have to do so much ifs:
local validColors = {["black"] = colors.black, ["white"] = colors.white} --Expand the table to all colors, this kust an example
local function isValidColor(col)
  if validColors[col:lower()] then --check if its a valid number
	return true --return true if its a valid number
  else
	return false --return false if it isnt a valid color
  end
end

function setBC(col)
  if isValidColor(col) then --if col is a valid color
	term.setBackgroundColor(validColors[col:lower()]
  else
	error("not a valid color!",0)
  end
end
I hope you understand it
Why not just return the colour?
local validColors = {["black"] = colors.black, ["white"] = colors.white}

local funciton parseColor(col)
  return validColors[col:lower()]
end

function setBC(col)
  col = parseColor(col)
  if not col then
	error("not a valid color!", 2)
  end
  term.setBackgroundColor(col)
end
Also notice the throwback level of 2 on the error call there, this is better as it tells them where they went wrong, not just that they went wrong.

#5 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 19 September 2013 - 01:54 AM

I'm happy to see feedback in just 12 hours :D

View Posttheoriginalbit, on 18 September 2013 - 02:11 PM, said:

1. Take a look into pastebin, its good for hosting large code and there is a program included in ComputerCraft to download from pastebin
I was looking at what could've I forgotten, that was pastebin, thanks for that :D Will put that link now!

View PostFreack100, on 18 September 2013 - 03:34 PM, said:

A little improvement so you don't have to do so much ifs:
local validColors = {["black"] = colors.black, ["white"] = colors.white} --Expand the table to all colors, this kust an example
local function isValidColor(col)
  if validColors[col:lower()] then --check if its a valid number
	return true --return true if its a valid number
  else
	return false --return false if it isnt a valid color
  end
end

function setBC(col)
  if isValidColor(col) then --if col is a valid color
	term.setBackgroundColor(validColors[col:lower()]
  else
	error("not a valid color!",0)
  end
end
I hope you understand it
After looking at the "col:lower()" part I finally figured out that you can manipulate variables. I didn't know that, and it'll help me out very much, thanks! Also, the idea is pretty good.

View Posttheoriginalbit, on 18 September 2013 - 02:11 PM, said:

2. Take a look into parsing the colours so that people can supply strings or the colours themselves, there was a thread in Ask a Pro a month or two back where I helped someone with colour parsing
3. I looked at this when the contents was only testing spoilers, please use the view button next time instead of the post button
2. I don't really know why parsing colors would be useful, still monitors and computer-related things support only 16 colors. Maybe I could do that, idk.
3. Thanks for the tip, I didn't notice the button :D

Just 1 question: what do the error levels mean? Like "error("not a valid color!", 2)?

#6 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 19 September 2013 - 11:56 AM

View Postrobotica34, on 19 September 2013 - 01:54 AM, said:

2. I don't really know why parsing colors would be useful, still monitors and computer-related things support only 16 colors. Maybe I could do that, idk.
What Freack100 posted, and then I fixed would be classed as colour parsing. Not quite complete, because it still only supports strings, not numbers and strings, but its a start.

View Postrobotica34, on 19 September 2013 - 01:54 AM, said:

Just 1 question: what do the error levels mean? Like "error("not a valid color!", 2)?
Its all about who the error is going to blame.
Level 0 — Blames no one, there is no filename or line number, just the red message on the screen
Level 1 (or none provided) — Blames your function, the file name is the name of your file, and the line number is where the error was called
Level 2 (great for APIs) — Blames the person who called your function, the file name is theirs, the line number is where they called your function
..... this continues until eventually the levels get all the way back to the bios.

Examples
Spoiler


#7 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 20 September 2013 - 12:46 AM

Thanks for the post, I analyzed it and learnt even more :D
One thing about parsing colors - how can I detect that the number value of the color is "pure" (let's say, 4 for magenta, but 3 is white and orange)? Is there a formula?

#8 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 20 September 2013 - 04:22 AM

View Postrobotica34, on 20 September 2013 - 12:46 AM, said:

One thing about parsing colors - how can I detect that the number value of the color is "pure" (let's say, 4 for magenta, but 3 is white and orange)? Is there a formula?
Yes there actually is, without going into too much detail as to why this very nice design choice was made, the colours are actually on a binary scale. This means that

Quote

white = 2^0
orange = 2^1
...
red = 2^14
black = 2^15
Knowing this, and knowing math, we can actually reverse a 2n number using log2(n). Lua doesn't have an implementation however so we must make one like so
local function log2(num)
  return math.log(num) / math.log(2)
end
Now what this will do is it will return us a number which we can the validate. Something like this would do the trick
local function validateColor(col)
  col = log2(col)
  if col < 0 or col > 15 then
	return false --# it is out of bounds, white is 2^0 and black is 2^15
  end
  if col % 1 ~= 0 then
	return false --# it is not a whole number, meaning its a combination of colours
  end
  return true
  --# all the above can be compacted down to this
  return col >= 0 and col <= 15 and (col % 1) == 0
end
Now the second if conditional may look confusing to you with the % operator, if it does open the spoiler and read, if not, just skip the spoiler
Spoiler

Now if you wanted to do something a little more true of how ComputerCraft deals with `impure` colors you can do the following
local function parseColor(col)
  return 2 ^ math.floor(math.log(col) / math.log(2))
end
What we do there is break it down to the number from 0—15, we then round it down, so 5 is still 5, 5.1 is 5m but 5.9 is also 5 and then we return the binary of that number. So for example 3 would become 2. log2(3) equals 1.58 rounded down equals 1, 2 ^ 1 equals 2.
The reason we do this math.floor is because of the way they do it in the ComputerCraft code, without going into too much detail and explanation why Java works in this way, in the CC code they cast a double (iirc) into an integer, and the way that Java deals with double/float to int casting is to round the numbers down making the double 1.1 equal 1 when its an integer, or the double 1.9 also equal 1 when its an integer.
Now if you actually check the above method with how ComputerCraft actually does this you will notice that its the same, try the following
local function parseColor(col)
  return 2 ^ math.floor(math.log(col)/math.log(2))
end

local c = colors.combine(colors.white, colors.orange)
term.setTextColor(c)
print("ComputerCraft's colour parsing")
term.setTextColor( parseColor(c) )
print("Our colour parsing, its the same color")

Hope this all makes sense and helps

— BIT

#9 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 20 September 2013 - 05:59 AM

Hello,
I'm currently working on an update, that's why I'm not replying.
I somehow get this error in this line:
if type(color) ~= "string" or type(color) ~= "number" then error("string or number expected, got "..type(color), 2) end
It says:
"pcall: string or number expected, got string" (pcall is because i'm on a lua interpreter).
What is the deal here?
FYI, inputs are drawLine(color, startx, endx, height).

EDIT:
I finally got it. The problem was, it always checked the second conditional, causing it to break, because one variable can't have two types. Instead, I did
if type(color) ~= "string" then
  if type(color) ~= "number" then
	error("string or number expected, got "..type(color), 2)
  end
end
SECOND EDIT:
It wasn't the problem because of ifs, it's because I used OR instead of AND. Derp.

#10 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 20 September 2013 - 06:22 AM

View Postrobotica34, on 20 September 2013 - 05:59 AM, said:

What is the deal here?
It is because of how the OR works. Basically what you're saying here is that `color` needs to be both a string and a number.

Quote

OR
true or true = true
true or false = true
false or true = true
false or false = false
So lets say what you supply is a boolean, type(color) ~= "string" will resolve to true because a boolean is not a string, as seen above nothing else in the statement can change the result of true when using ORs, so it ignores the rest of the conditional and performs the contents of the if statement. What you need to do is use AND

Quote

AND
true and true = true
true and false = false
false and true = false
false and false = false
That way if it is not a string and not a number, then it needs to error.

Alternatively
Spoiler


#11 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 20 September 2013 - 08:16 AM

You maybe saw my edit for solution, but I didn't figure out that I should use AND instead of OR. Thanks :D
BTW, I'm rewriting a big portion of my code, so it'll take quite a while, but should be done in under 20 minutes.

#12 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 20 September 2013 - 09:16 AM

Sorry if the update is running late, been playing around with other things, that's why I'm late. Also putting in a lot of error checking.

#13 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 20 September 2013 - 11:51 AM

The update is out! Making this post for those who only check notifications. Check the OP for details.

#14 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 21 September 2013 - 08:30 AM

I would like to receive some feedback :) Been feeling alone, no feedback on the update :( Also, I'm working on v1.2 - shrinking code, reimplementing drawBox, mkButton, checkIfClicked, turnOnButton, turnOffButton, also error-checking is being redone - I'll now give more exact information on where they went wrong, not that they just went wrong somewhere when calling my function. So, stay tuned!

#15 Vilsol

  • Members
  • 194 posts
  • LocationStudy: United Kingdom Native: Latvia

Posted 21 September 2013 - 12:10 PM

Quite a lot of useless code.
For example:
for k, v in pairs(availableColors) do
	  if input == v then
		 correctColor = true
		 break
	  else
		 correctColor = false
	  end
	end
Could be just
for k, v in pairs(availableColors) do
	  if input == v then
		 correctColor = true
		 break
	  end
	end

The function wrapPer is just a huge mess, which I don't understand. You can just use peripheral.getNames() and check against the side table.
The function fillBox actually is drawBox. And also, why don't you just use your own background color function?

#16 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 21 September 2013 - 12:23 PM

Thanks for the peripheral tip, but actually I can't do
 for k,v in pairs(availableColors) do
 if input == v then
  correctColor = true
  break
 end
end 
because if color is incorrect I will have nil and I don't want to do that. I could also check if correctColor == nil, but it's easier to do if correctColor.
drawBox is now update (working on 1.2) and removed like 150 lines of code already by calling a main function for all error-checking.
I'm a beginner and it's a pain in the ass to figure out how to do things easily. I barely use "help api" for something.

P.S. When I was playing "illegal" Tekkit about two years ago, I used a switcher made by Vilsol, it was in Latvian. Is that the same you? :D Btw, I live in Lithuania, so I live near you :P

#17 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 21 September 2013 - 12:27 PM

View Postrobotica34, on 21 September 2013 - 12:23 PM, said:

Thanks for the peripheral tip, but actually I can't do
-code snip-
because if color is incorrect I will have nil and I don't want to do that. I could also check if correctColor == nil, but it's easier to do if correctColor.
set it to false first, before the loop. Also nil will resolve to false in an if statement when you do the following
if correctColor then
  print("It was a value! Any value, except false or nil")
else
  print("It was false or nil")
end


#18 Vilsol

  • Members
  • 194 posts
  • LocationStudy: United Kingdom Native: Latvia

Posted 21 September 2013 - 12:40 PM

View Postrobotica34, on 21 September 2013 - 12:23 PM, said:

Thanks for the peripheral tip, but actually I can't do
 for k,v in pairs(availableColors) do
 if input == v then
  correctColor = true
  break
 end
end 
because if color is incorrect I will have nil and I don't want to do that. I could also check if correctColor == nil, but it's easier to do if correctColor.
drawBox is now update (working on 1.2) and removed like 150 lines of code already by calling a main function for all error-checking.
I'm a beginner and it's a pain in the ass to figure out how to do things easily. I barely use "help api" for something.

P.S. When I was playing "illegal" Tekkit about two years ago, I used a switcher made by Vilsol, it was in Latvian. Is that the same you? :D/> Btw, I live in Lithuania, so I live near you :P/>

Yes that was my switcher ^_^ (And yes it was in Latvian).
What you can do is after the for loop make a check if the correctColor is still false, just error out.

#19 robotica34

  • Members
  • 28 posts
  • Locationpcapi.location

Posted 22 September 2013 - 12:40 PM

Help me!
 if type(side) ~= "string" then
error("insert error here "..type(side), 2)
end 
If I enter a side with type string, it outputs me this:
 pcapi:105: attempt to call string 
WTF?!!
BTW, line 105 is
 if type(side) ~= "string" then 
What should I do?

#20 AgentE382

  • Members
  • 119 posts

Posted 22 September 2013 - 06:59 PM

View Postrobotica34, on 22 September 2013 - 12:40 PM, said:

Help me!
 if type(side) ~= "string" then
error("insert error here "..type(side), 2)
end 
If I enter a side with type string, it outputs me this:
 pcapi:105: attempt to call string 
WTF?!!
BTW, line 105 is
 if type(side) ~= "string" then 
What should I do?
Would you post the full function, please?





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users