lainchan / λ

What are you working on? Version 2.0

Molly Millions · 2018-09-12 09:07
The last thread hit the limit so I would like to create a new one. What are you working on? Share your code and ideas about projects. Made FizzBuzz implementation in Lua (5.1) using functional programming techniques. I had to implement zip, and map but that was easy. Overall I have to say that I enjoy programming in Lua. Lua function getFizzOrBuzz (a) if a % (3 * 5) == 0 then return 'FizzBuzz' elseif a % 3 == 0 then return 'Fizz' elseif a % 5 == 0 then return 'Buzz' else return "" .. a -- will return a string and not a number end end function map (t, f) local result = {} for k, v in ipairs(t) do result[#result + 1] = f(v) end return result end function sequence (n, f) local result = {} for i = 1, n do result[#result + 1] = f(i) end return result end function zip (t1, t2) local result = {} for i = 1, math.min(#t1, #t2) do result[#result + 1] = t1[i] result[#result + 1] = t2[i] end return result end function fizzBuzz () local t = sequence(100, function (x) return x end) local newLine = sequence(100, function (x) return '\n' end) -- return unpack(zip(map(t, getFizzOrBuzz), newLine)) -- returns muliple results to pass to print() return zip(map(t, getFizzOrBuzz), newLine) -- returns a table for table.concat input end function main () -- print(fizzBuzz()) print(table.concat(fizzBuzz())) end main()
Drifter · 2018-10-07 15:24
I'm currently writing a TUI IRC client in C and it's been a challenging, but yet fruitful task. The most challenging part isn't actually the ANSI code stuff, but coming up with a good abstraction to draw the screen. Also, it's the first time I'm doing any 2D stuff. The client is heavily inspired on very old TUI IRC clients like the initial irc (the original one that came with the IRC server package back in the early 90s), ircII, epic and irssi. So far, I am enjoying it. Let's see where this goes.
Nguoi La · 2018-10-07 15:36
>>10399 Currently developing a 2D top-down game, and I'm really considering ditching OpenGL based rendering for custom raycasting (or maybe even raytracing) rasterizer in OpenCL. In OpenGL I would basically need to do some "hacks" to get shadows and lightning working well, but in raycasting it's free, I am only wondering if it is actually a reasonable option so that I won't hit some obstacle just to get back to OpenGL again. Any tips?
Von Neumann · 2018-10-08 06:51
Did this thread just get remade? I'm sure there was a guy working on some kind of reverse-engineering tool in this thread. You could press buttons and see the machine code or something and thereby "feel your way" around the hardware or something. Even if you call this thread "2.0", I'm sure it's more like 2.1.
Ivan Petrov · 2018-10-08 09:08
>>10779 It probably depends on what do you want in the end. If your willing to add some limitation then a grid based raycatser (think Wolfenstein 3D) isn't that hard to implement. Yes, Wolfenstein 3D was w 2.5D FPS game but the mechanic in a 2.5D FPS is really the same as in a 2D top-down game (the difference is in the way you draw the game on the screen). If your interested then have a look in this link: https://lodev.org/cgtutor/raycasting.html I'm slowly creating a grid based first person perspective dungeon crawler myself and had implemented my own raycaster for this puprose. It took me few hours to make it work (however it still have some bugs I need to fix).
BloodCat · 2018-10-08 16:53
A small IRC written in Nodejs that doesn't rely on any external libraries.
word · 2018-10-08 17:36
>>10788 IRC client or server?
J.C. Denton · 2018-10-08 17:58
>>10790 IRC isn't really accurate I apologize. Basically it's a messaging app that does what IRC does, but with more functionalities.
Crazy Jake · 2018-10-08 18:29
>>10784 I made some entry tests, and it's quite slow. Basically what I did was cast rays from the center of the screen to the boundary pixels, the actual map is grid-based and was scaled down 64x, I also didn't read the map for every pixel, I did it only when the map coords changed. And it was a very basic version with only white for empty and black for wall, it looked quite cool (and I also accidentally created a really cool glitch which I might upload later), it actually looked like top-down 3d due to the shadows casted by blocks. Still I guess it was too unoptimized, some pixels were set by many rays, which is redundant and so you had quite an overhead even with a 800x600 display. I suppose that there are many optimizations to be made, for example pre-calculating the "step" vectors for every ray, so that no ray touches the same pixel twice (and that also reduces the overall number of steps). I benchmarked the unoptimized version on a very slow laptop, but still - it would need to be fast, since in the final version I would have to for example combine the colors (from textures) that the ray hits to get the final color etc. Also the quite sad news is that this old laptop of mine doesn't even support OpenCL, so everything would have to be CPU-side after all.
dup · 2018-10-08 21:01
>>10793 Sounds interesting. You should check out IRC's RFCs (if you haven't already) for further inspiration. I like how brain dead simple IRC really is compared to other chat systems. XMPP comes to mind. IRCv3 WG ( https://ircv3.net ) is currently trying to improve certain client-side features too.
over · 2018-10-09 04:40
>>10798 I'll take a look, thanks a bunch! :)
Church · 2018-10-09 10:16
>>10794 >cast rays from the center of the screen to the boundary pixels Wait your casting 2800 rays? Well that could be a litle slow and your not taking advantages from the fact that the map is a grid if your calculating it on the upscaled version of the map (the one your displaying on the screen). OK, here what I do. First some assumptions. The grid is made from 1 on 1 squares, the position of a player is described by floating points, so he could be in different places of a given square. The player has a 60 deg FOV. All calculations are made on this "downscaled" world. When I want to draw someting I just upscale it by 40 and end up with a screen size of 640x480 pixels. You can see on the first image how this looks from the top view. The blue lines indicates integer values on the plane, the white boxes are walls, the red line is my FOV, and the yellow is the direction I'm looking in. For the top down-view I cast 85 rays (I move the angle of casting a ray by PI / 256). Yes, the algorithm will work faster if the ray hits the wall sooner but the max distance (in top down view) is sqrt(12^2 = 16^2) = 20 (for my downscale world of 12x16, from one corner to a other). Now after I casted a ray in a given dirrection I need to calculate the next step so I will only check the intersection of the blue and red line (the link I posted earlier shows how can you make those calulations). In other words if I would consider a ray going straight up on the picure of the top down view then I would need to check only 8 times did I hit the wall before I hit the obstacle on that picure. If I would do the same thing on a upscaled version then I would check 8*40 places did my ray hit something. Thats why I asked about the grid map, because its not that expensive if you would count it on the small version and then upscale it. The downsite is that, the walls (object that the ray interacts) need to 1 on 1 squares on the grid. For a bonus I'm also posting a "3D" view of that sceen. Here I need to cast 640 rays (one for every column of pixels on my screen). It might be a little dark.
swap · 2018-10-10 15:13
>>10810 The thing is that I want raycasting specifically for the per-pixel rendering, with that you can do cool stuff, like really nicely looking mists, lightning, shadows, etc. In other words it has to be full resolution for me, I'm not really doing a retro demo, but an actual game. (also note: it does not translate to 3d, it only is the top-down 2d like in your first screenshot) Anyway, I kind of figured out that I can transfer all the computations to the GPU in OpenGL, basically - every boundary pixel is a vertex, and I create a line from those pixels to the center of the screen. This is actually super fast and probably comparable to standard triangle-based rendering. The only downside now is that I have to introduce an additional mechanism to do the occlusion (i.e. shadows), since the stuff runs in parallel I can't do it in one pass (i.e. hide a pixel that was rendered BEFORE the current one). It's a quite interesting rendering method and potentially a fast one, I will need to experiment a bit more and see what I can make out of it.
car · 2018-10-10 18:12
>>10782 >Did this thread just get remade? Yes. The opening poster mentioned the previous thread hit the bump limit. >I'm sure there was a guy working on some kind of reverse-engineering tool in this thread. You could press buttons and see the machine code or something and thereby "feel your way" around the hardware or something. Even if you call this thread "2.0", I'm sure it's more like 2.1. That's me. I checked because of your post and I actually barely mentioned it here: >>1035 It can be used as a reverse-engineering tool, and that's one use I have planned for it, but I do prefer to think of it as more of an authorship tool. It's an authorship tool that contains reverse-engineering tools just because of how naturally that fits into the rest of the model. The idea with buttons is, firstly, that position, not character value, determines what happens and that the tool will aid as much as it reasonably can in writing machine code programs. I have also made these other posts concerning it: >>7779 >>10144 >>10145 >>10412 >>10681 I believe you mistook this thread for >>10408 ; it's a shame there have been no thoughts about it there. I suppose the two threads are actually rather redundant, but I suppose there's no reason to merge them, yet. Here's another screenshot, this time in st; it works well enough with a dark background and whatever values for standard colors are used, but I prefer the gnome-terminal default colors on a light background. If you're interested in discussing any aspect of this tool, I'd be glad to.
x<->y · 2018-10-10 20:00
this thread -> OP -> 2018-09-12 09:07:07 other thread -> OP -> 2018-09-14 03:41:45 The other thread's OP failed to do something as basic as checking the catalog.
let · 2018-10-10 22:01
Guys, help me please, i need to write "technical plan", but i never worked on serious software before. It should be portal that is: 1.blogging platform 2. e-shop with books 3. personalized calendar 4. programming language similiar to both scheme/basic C++ embedded into browser. 5. system of recommendations based on user activitiy (blogs he reads/writes) 6. Search by tags Project should be in spring boot/javascript. We have nothing yet. What should i write in a plan?
JARGON · 2018-10-10 23:03
>>10839 >We have nothing I'm going to assume this is a group effort and not a standalone one. If so, then delegate. First ask people what are they most comfortable with and if they can't make up their minds or if they want to do the same thing then you have to choose for them. One person does the blogging part, the other the e-shop, and so on. If there are few people to do it then either get more people to help you or people are going to feel strained. (But I guess it depends on people's resilience to stress.) If you see that two people can realize a single task faster then do it. I never wrote a technical plan either, but I'd start by defining exactly what PLs (programming languages) are best suited for this task - at least in its first iteration - and not complicate what's already a somewhat challeging task. Remember that when you start a project you want something to show FAST and WORKING as per the product's specification/requirements. You'll also need to define what resources are you going to need like hardware, software, etc in case you need to outsource some parts of the project. Like a web hosting provider or something like that. Is it in-house? Etc. You need to consider and define these things too. Tentative budgets, etc. >programming language similiar to both scheme/basic C++ embedded into browser. I don't fully understand this, but writing a blog platform in C++ is probably not a good idea, at least in its first iteration. You should probably write it in some easy to prototype language like JavaScript or Python like you mentioned later in your post. Yes, even the backend, you should probably use something like Node.js. Start by unambiguously defining phases of your plan. And on each one you should set goals which MUST be met in a certain time span, and so you can move on to the next one. Set a time when you guys get to work together (and NOT goof around) and just write code. Make sure you write unit tests before moving on to the next goal. The code MUST work according to the specification otherwise you'll be delivering defective and unreliable code which customers don't like - as you might guess. You need to keep this plan up-to-date as well, if something doesn't go according to plan you need to update it and explain why in your reasoning (learning from your mistakes is also good for career building). Keep a daily log about what you guys achieved, etc. And checkpoint with your manager/customer about the project, let them check it out once in a while to see how they feel about it and keep it clear that's a beta product too, don't make them feel like that's the finished product. Not sure if this was what you were asking for, but I hope my post was somehow helpful.
Turner · 2018-10-14 23:43
I just made this. I need to manage my finances better so I thought an app might help. It's my first true app in JavaScript. It' still kinda buggy (I know that you can get NaN because the inputs are not sanitized properly) but most bugs should be gone. <!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Finances</title> <meta http-equiv="cache-control" content="max-age=0"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT"> <meta http-equiv="pragma" content="no-cache"></head> <body onload="tentom()"> <style> body { background: #DDDDFF; color: #333333; font-family: sans-serif; } a { text-decoration: none; color: #7777FF; } a:visited { text-decoration: none; color: #7777FF; } a:hover { text-decoration: none; color: #DCCC66; } td { padding: 2px; } .cent { text-align: center; } .main { background-color: #FAF9FF; padding : 30px; } </style> <br><br><br><br> <table border="0" width="100%" class="cent"><tr valign="top"> <td class="left" width="15%"></td> <td class="main" height="800" align="left"> <a onclick="tentom()">This month</a>     |     <a onclick="dlouho()">Long term</a><hr> <div id="mcont"></div> </td><td class="right" width="15%"></td></tr></table> <script> var count = 1; var ctwo = 1; var cc = 1; function calc() { var celk = 0; if (count - 1 > 0 ) { var z = document.getElementById("vysl"); if(z.innerHTML != "") { var celk = parseInt(z.innerHTML); } while(cc<count) { var cfnn = "expmon" + cc; var xx = document.getElementById(cfnn); var bb = xx.value; if(bb == "") { bb = 0; } celk = parseInt(celk) + parseInt(bb); cc++; } while(ctwo<count) { var cfn = "expnm" + ctwo; var x = document.getElementById(cfn); var a = x.value; cfn = "expmon" + ctwo; x = document.getElementById(cfn); var b = x.value; cfn = "sp" + ctwo; x = document.getElementById(cfn); x.innerHTML = a + "&nbsp;:&nbsp;&nbsp;&nbsp;" + b; ctwo++; } z = document.getElementById("meza"); z.innerHTML = "<hr>"; z = document.getElementById("budget"); if (z.value == "") { z.value = 0; } var bud = parseInt(z.value); z = document.getElementById("bud"); z.innerHTML = "   " + bud + "<br>-  "; z = document.getElementById("vysl"); z.innerHTML = celk; z = document.getElementById("carb"); z.innerHTML = "<hr>"; z = document.getElementById("vyslb"); z.innerHTML = bud - celk; z = document.getElementById("mezb"); z.innerHTML = "<br><br>"; } } function addex() { var maincont = document.getElementById("exps"); var expspana = '<span id="sp'; var expspanb = '">'; var expfielda = '.  <input type="text" id="expnm'; var expfieldb = '">  :  <input type="text" id="expmon'; var expfieldc = '"></span><br>'; maincont.insertAdjacentHTML("beforeend", expspana + count + expspanb + count + expfielda + count + expfieldb + count + expfieldc); count++; } function addspen() { var maincont = document.getElementById("exps"); var expspana = '<span id="sp'; var expspanb = '">'; var expfielda = '.  <input type="text" id="expnm'; var expfieldb = '"></span><br>'; maincont.insertAdjacentHTML("beforeend", expspana + count + expspanb + count + expfielda + count + expfieldb); count++; } var contone = '<br>Your budget:<br><input type="text" id="budget"><br><br>Your expenses:<br><div id="exps"></div><span id="meza"></span><span id="bud"></span><span id="vysl"></span><span id="carb"></span><span id="vyslb"></span><span id="mezb"></span><a onclick="addex()">Add an expense</a><br><br><a onclick="calc()">Calculate</a>'; var conttwo = '<br>Your monthly spendings:<br><div id="exps"></div><span id="meza"></span><span id="bud"></span><span id="vysl"></span><span id="carb"></span><span id="vyslb"></span><span id="mezb"></span><a onclick="addspen()">Add a month</a><br><br><a onclick="graph()">Make a graph</a>'; function tentom() { count = 1; ctwo = 1; cc = 1; var maincont = document.getElementById("mcont"); maincont.innerHTML = contone; } function dlouho() { var maincont = document.getElementById("mcont"); count = 1; ctwo = 1; cc = 1; var maincont = document.getElementById("mcont"); maincont.innerHTML = conttwo; } function graph() { z = document.getElementById("mezb"); var hhh = '<br><svg height="500" width="900"> <path d="M 2 450 l 898 0" stroke="black" stroke-width="3" fill="none" />'; var pa = '<path d="M '; var pb = ' Z" stroke="#FFCCCC" stroke-width="2" fill="#FFCCCC" />'; var pend = 'Sorry, your browser does not support inline SVG. </svg>'; while(cc<count) { var cfnn = "expnm" + cc; var xx = document.getElementById(cfnn); var bb = xx.value; bb = bb / 1; var hor = cc * 50; var ver = 445 - bb; var hh = pa + hor + " 445 L " + hor + " " + ver; hor = hor + 30; hh = hh + " L " + hor + " " + ver + " L " + hor + " 445 " + pb; hhh = hhh + hh; cc++; } hhh = hhh + pend; z.innerHTML = hhh; cc = 1; } </script> </body></html>
nil · 2018-10-15 10:06
>>10903 If the graph goes beyon its borders, just change this line bb = bb / 1; to something bigger like bb = bb / 2; or bb = bb / 10; or bb = bb / 20;
fsociety · 2018-10-16 14:07
>>10399 I'm learning mysql(i) and php to create a website like a smaller scale YouTube an/or bitchute. If anyone has done something like this before I would love advice. I am working from 1 database and have a user's table and a table for each video I have up there for holding posted comments by users
string · 2018-10-16 23:38
>>10936 just curious, but why php. i've heard bad things.
setq · 2018-10-17 09:52
Planning to reimplement this thing in go https://github.com/php-pm/php-pm
Drifter · 2018-10-17 12:59
I made a java program that extracts the Apks of all your installed Android apps for backup purposes in Android 8.1. I'm planning to expand it so it can install them back automatically without user interaction. I haven't had much time to work on it lately but I'd love to finish it anytime soon since I seriously need to flash my phone and it's such a bother to manually install everything again.
Judge Fang · 2018-10-19 18:32
>>10399 Just made this thing in 4 hours and about 400 lines, it has sound (also my first OpenAL program).
Molly Millions · 2018-10-19 19:24
>>11020 That's fuarrrking sweet lain
Aristóteles Amadópulus · 2018-10-21 18:59
I decided to make a terminal application to browse lainchan after finding this reddit terminal viewer (https://github.com/michael-lazar/rtv). I also decided to make it in .NET Core because Core is actually pretty cool. Would you use a terminal to browse lainchan? Here's the code I have after a ~20 minutes of work. So far, it just displays 10 posts from mega. Obviously this has a long way to go, but I think it's a fun project. using System; using HtmlAgilityPack; namespace LainchanGet { class Program { static void Main(string[] args) { string Url = "https://lainchan.org/mega"; HtmlWeb web = new HtmlWeb(); HtmlDocument doc = web.Load(Url); var threadNumber = 1; var maxThreads = 10; var threadBreak = "------------------------------------------------------------"; while (threadNumber <= maxThreads) { var threadTitle = doc.DocumentNode.SelectNodes("/html/body/div[2]/form[2]/div[" + threadNumber + "]/div[2]/p/label/span[1]")[0].InnerText; var postTime = doc.DocumentNode.SelectNodes("/html/body/div[2]/form[2]/div["+ threadNumber + "]/div[2]/p/label/time")[0].InnerText; var opPost = doc.DocumentNode.SelectNodes("/html/body/div[2]/form[2]/div[" + threadNumber +"]/div[2]/div")[0].InnerText; Console.WriteLine(threadBreak); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(threadTitle + " @ " + postTime); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(opPost); threadNumber ++; } } } }
Jet Black · 2018-10-22 00:40
>>11053 Nice, I was actually making something similar but using Scheme.
Tyrell Wellick · 2018-11-12 11:34
Here's an offline HTML version of Category Theory for Programmers by Bartosz Milewski. http://0x0.st/slvB.gz $ sha1sum ctfp-lain-20181111.tar.gz 344ccb91b0cfd2a3b1302f8c7c6ccd8a74f6872a ctfp-lain-20181111.tar.gz Source: https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/ This includes an option to order the dead tree version. LaTeX and PDF versions: https://github.com/hmemcpy/milewski-ctfp-pdf Differences between this scrape and the github version: - Some chapters of the book link to other posts by the same author that are not part of the book proper. Those are also included in this version. - The github version replaces the inline anchor images with the full versions they link to. This version keeps the smaller images linking to the full images, so that those reading on a light-on-dark theme do not get large white patches interspersed in the text. The full images are included in the scrape and accessible through the smaller images, just like on the author's blog. - The author seems to be silently updating the chapters by adding more images of commuting diagrams. For example, in the github version the Enriched Categories chapter contains two images, while this scrape contains nine. This is also the main reason for versioning the scrape with the date. Put whatever custom styling you want into style.css and the pages will apply it. Do not fear the monad.
Lunch · 2018-11-12 21:22
The link conversion step from >>11324: class C: LINKS_STR = '''href=['"]https://bartoszmilewski.com/[0-9]+/[0-9]+/[0-9]+/([-\w]+)/['"]''' LINKS_RE = re.compile (LINKS_STR) def work_links_table (indir): all = os.listdir (indir) table = {} for name in all: left, sep, right = name [:-4].partition ("-") old = table.get (right) if old is not None: raise ValueError ("duplicate {} {} {}".format (old, left, right)) table [right] = left return table def work_links_editor (table, text, name): def repl (mob): key = mob.group (1) val = table.get (key) if val is None: g0 = mob.group () print (name, '->', g0) return g0 else: return 'href="{}-{}.htm"'.format (val, key) return C.LINKS_RE.sub (repl, text) def work_links (indir, outdir, rest): table = work_links_table (indir) edit_loop (indir, outdir, lambda text, name: work_links_editor (table, text, name)) And the generic editing loop: def edit_name (indir, outdir, name, editor): with open (ospa.join (indir, name), "r") as f: text = f.read () text = editor (text, name) with open (ospa.join (outdir, name), "w") as f: f.write (text) def edit_loop (indir, outdir, editor): all = os.listdir (indir) # print ("\n".join (all)) for name in all: edit_name (indir, outdir, name, editor)
Gyula Kovacs · 2018-11-14 11:25
Cutting out the extraneous WordPress stuff from >>11324 does not require html parsing, because they are nice enough to include an ad section immediately after the actual content. The editing loop from above is reused with a different editor function. class C: CUT_START_STR = '<div class="post-content">' CUT_START_RE = re.compile (CUT_START_STR) CUT_FINISH_STR = '<div id="atatags-' CUT_FINISH_RE = re.compile (CUT_FINISH_STR) def work_cut_editor (text, name): mob = C.CUT_START_RE.search (text) if mob is None: raise ValueError ("start {}".format (name)) stfrom, stto = mob.span () mob = C.CUT_FINISH_RE.search (text, stto) if mob is None: raise ValueError ("finish {}".format (name)) fifrom = mob.start () return text [stfrom : fifrom] def work_cut (indir, outdir, rest): edit_loop (indir, outdir, work_cut_editor) This also illustrates another advantage of using compiled regular expressions, besides avoiding recompilation on every use of a string pattern, which is already mitigated somewhat by the implementation caching the compiled versions of the most recent patterns. The search method of compiled regexps allows specification of search bounds, while the module-level function does not and would require slicing. https://docs.python.org/3/library/re.html#re.search https://docs.python.org/3/library/re.html#re.Pattern.search
stack · 2018-11-15 23:59
Relinking images for >>11324 involves two steps. The github version simply looks for all image tags and the href of their parent anchors. https://github.com/hmemcpy/milewski-ctfp-pdf/blob/master/src/scraper.py Unfortunately, in the extra non-book chapters linked from the book there are images that are not wrapped in anchors. Rather than special-casing those, uniform treatment is maintained by scanning for images and anchors separately. grep -o -i -e '<img [^>]*>' -r "$DIR/cut" > temp/images01.txt sed -r -e 's#^[^:]*/([^/-]*)-[^/:]*:<[^>]* src="([^"]*/([^/"?]*)([?][^/"]*)?)"[^>]*>$#\1 src \3 \2#' temp/images01.txt > temp/images02.txt grep -o -i -e '<a[^>]*href="[^"]*"[^>]*>' -r "$DIR/cut" > temp/images11.txt grep -E -i -e '[.](gif|jpg|jpeg|png)"' temp/images11.txt > temp/images12.txt sed -r -e 's#^[^:]*/([^/-]*)-[^/:]*:<a[^>]*href="([^"]*/([^/"]*))"[^>]*>$#\1 href \3 \2#' temp/images12.txt > temp/images13.txt cat temp/images02.txt temp/images13.txt > temp/images21.txt This produces lines like the following: c05 src initial.jpg https://bartoszmilewski.files.wordpress.com/2014/12/initial.jpg?w=285&h=300 c15 src yoneda1-e1440290035365.png https://bartoszmilewski.files.wordpress.com/2015/08/yoneda1-e1440290035365.png?w=263&h=259 c05 href initial.jpg https://bartoszmilewski.files.wordpress.com/2014/12/initial.jpg c15 href yoneda1.png https://bartoszmilewski.files.wordpress.com/2015/08/yoneda1.png Note that not all pairs of anchor and full images have matching names, which is another source of asymmetry. This list is then processed through the editing loop with an editor that maintains separate handling of anchors and images. class C: IMAGES_HREF_STR = '''href=['"](https://bartoszmilewski.files.wordpress.com/[^'"]+)['"]''' IMAGES_HREF_RE = re.compile (IMAGES_HREF_STR) IMAGES_SRC_STR = ''' src=['"](https://bartoszmilewski.files.wordpress.com/[^'"]+)['"]''' IMAGES_SRC_RE = re.compile (IMAGES_SRC_STR) def work_images_table (data): with open (data, "r") as f: text = f.read () table = {} for line in text.splitlines (): id, type, name, url = line.split () table [(id, type, url)] = name return table def work_images_editor (table, text, name): id = name.partition ("-") [0] def repl_href (mob): url = mob.group (1) name = table [(id, 'href', url)] return 'href="../img/href/{}/{}"'.format (id, name) def repl_src (mob): url = mob.group (1) name = table [(id, 'src', url)] return ' src="../img/src/{}/{}"'.format (id, name) text = C.IMAGES_HREF_RE.sub (repl_href, text) text = C.IMAGES_SRC_RE.sub (repl_src , text) return text def work_images (indir, outdir, data, rest): table = work_images_table (data) edit_loop (indir, outdir, lambda text, name: work_images_editor (table, text, name)) Since both tuples and strings are immutable, combining them produces valid dictionary keys.
Wirth · 2018-11-18 03:53
After cutting out unneeded content in >>11368 the page titles need to be restored to >>11324 somehow. All pages get a generic header based on the one the blog uses. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title></title> <link rel="stylesheet" type="text/css" href="../style.css" /> </head> <body> The originals are scanned for the titles, with a bit of cleanup: $ grep -o -i -e '<title>[^<]*</title>' -r "$DIR/raw" | sed -r -e 's/[ ]+[|][ \xc2\xa0]+Bartosz[^<]+</</' > temp/title.txt This list is then parsed and used with the editing loop from above. Since the title identification is simple a plain string replacement will suffice, without the need for regexps. class C: TITLE_STR = '<title></title>' def work_title_table (titles): with open (titles, "r") as f: text = f.read () return dict ( itertools.starmap ( lambda left, sep, right: (ospa.basename (left), right), map ( lambda line: line.partition (':'), text.splitlines ()))) def work_title_editor (table, text, name): return text.replace (C.TITLE_STR, table [name], 1) def work_title (indir, outdir, titles, rest): table = work_title_table (titles) edit_loop (indir, outdir, lambda text, name: work_title_editor (table, text, name)) The advantage of this approach is that it once again avoids the need for proper html parsing.
Mario Rossi · 2018-11-19 05:28
>What are you working on? Learning Ada, via way of porting Project Oberon to Ada. They're both wurthian languages so it isn't that big a stretch, but A) I need to also do the low level bootstrap which I'm just wholly avoiding at the moment, B) there are a few design choices I've just run with that will surely bite me later on. SETs specifically, I've gone with an integer array with a couple of helper functions to replicate "X in Y" but it is not a straightforward replacement and I think there will be a few other usages of SETs that will trip me up down the track. vectors may have been the better choice.
N|t3_0w| · 2018-11-19 06:10
BRL-CAD meh.
Trinity · 2018-11-19 13:45
>>11449 >wurthian languages What is that? I tryied to do a quick google search but google gave me links to english poetry so I guess it's not that. >A) I need to also do the low level bootstrap which I'm just wholly avoiding at the moment Couldn't you use a existing boot loader (like LILO or GRUB) to boot your OS?
Special Agent Bob · 2018-11-19 21:38
>>11456 Sorry, its Wirthian, and even that's a bit obscure , group of languages tied together by influence from https://en.wikipedia.org/wiki/Niklaus_Wirth Pascal, ada, Oberon,Modula-2 etc
The Phantom Phreak · 2018-11-22 10:58
While the next chapter blog links from >>11324 are regular anchors, the previous chapter links tend to have target="_blank" on the anchors so they open in a new window/tab. To clean up this asymmetry, and to achieve the wrapping from >>11437 the source files are looped over with a selectable file transformer. Since these two transformations do not need any extra contextual information, plain shell will do. #!/bin/sh set -e HEADER=header.txt FOOTER=footer.txt item_wrap () { cat "$HEADER" "$1" "$FOOTER" > "$OUTDIR/${1##*/}" } item_target () { sed -r -e 's/target="_blank"//g' "$1" > "$OUTDIR/${1##*/}" } main () { local name for name in "$INDIR"/*.htm do item_"$MODE" "$name" done } [ $# -lt 3 ] && { echo "args: mode indir outdir" exit 1 } MODE="$1" INDIR="$2" OUTDIR="$3" main The token that will become the command name is treated by the shell like any other token for the purpose of substitutions. This can be used as a function selector in a pinch, effectively making the looping function a higher-order function.
Turing · 2018-11-23 11:09
Working on AR experiments Wrote https://λ.name/track before I found out about ar.js Thinking of trying to create alternate reality using AR in my University's computer science club, where when you point your phone at the wall, the IRC channel is projected there the wall, when you point your phone at the bookshelves you see the status of the club's library, when you point your phone at the ceiling, it's replaced with the color of television, tuned to a dead channel. Something cute like that. So far though, I've got only a super simple demo working, but it's something.
John Titor · 2018-11-23 11:10
>>11504 Oh woops, forgot to attach GIF
Lady Jessica · 2018-11-23 14:53
>>11504 >when you point your phone at the ceiling, it's replaced with the color of television, tuned to a dead channel That should only happen when you point it at the sky and you are in a port city. A random ceiling in some random non-port city should not be enough.
Mentat · 2018-11-23 15:59
>>11505 >>11504 This looks fuarrrking amazing my man. What does it use to detect where to draw stuff?
The Fin · 2018-11-24 16:43
>>11508 The core of the detection is done using OpenCV, but I used some other person's tool to make it easy for myself. This is all done once: Record video -> select which objects to track (in this case, i picked a rectangle of four pieces of paper on the bulletin board) -> log the output of the tracking software -> transform that into data my javascript understands This is done live every time the website runs: get the projection of the four corners of the rectangle -> use CSS transforms to apply the inverse projection onto my HTML
Technician · 2018-11-25 02:17
>>10399 Putting a small node.js app on a k8s cluster. It gets a little confusing when the things that are supposed to make it easier end up making it more obscure and are just another thing to learn. Also I'm going to turn one of my old sites into a reactive app. Not sold on any of the big JS frameworks, but it's going to be between one of them. Probably the hardest part of thing is just all the plumbing I'm going to do with AWS. Take info from spreadsheet to DB, app makes DB calls and displays requested info. Anyone got tips for me?
Project 2501 · 2018-11-25 02:22
>>11504 >only a 3rd year student >already had 4 jobs well fuarrrk
Donna Hawthorne · 2018-11-25 23:18
>>11524 you too, can do this if you do side projects, have social skills, and the energy to apply for internships, and also live in/near a tech hub
Delilah · 2018-11-26 10:30
>>11523 Don't try to do too many new things at once. Start small and incremental. React > Vue > Most other things. By reactive app, do you mean RxJS? That stuff is good, but confusing and hard to write correctly. Try to take advantage of things that will save you work. Perhaps use Fargate, or maybe appsync (not sure if appsync is what I think it is), instead of managing EC2 instances yourself. Or maybe lambda/sqs but again those are new things that should simplify what you're doing but perhaps are complicated to learn on their own and thus not worth it, I dont knke. fyi AWS is pricey, make sure you're okay with that.
Junichi Fujiwara · 2018-11-27 23:51
>>11523 If you just want to get a project done quickly. Next.js and Nuxt.js are both good choices. Lightweight and easy to fling code If you want to learn, look at setting up an express app yourself. If you just want to learn react/vue, create-react-app/vue-cli both provides good defaults too
Ein · 2018-11-30 04:08
Designing an behavior tree based around continuations to use for async programming with asio in c++. its pretty fun so far, but i might end up not even using it for the program i was intending to write it for, i might try making a toy server with it once i finish though.
Unknown · 2018-12-01 06:59
>>10399 learning powershell so that I can begin automating our backup system. Need to have verification and restoration tests done automatically
SHODAN · 2018-12-02 01:28
>>11595 spent five hours trying to get tail-calls working properly, because the stack depth can get huge with so many callbacks. tried a number of things that would shrink the callstack, but not remove it. in the end it, turned out that it was a non-trivial copy constructor that was preventing it. this isnt even mentioned anywhere i looked on the topic. real shame tho, it was a fancy pseudo-linear function reference type that would ensure i would call the function exactly once, or pass it of to something else that will.
SHODAN · 2018-12-02 18:25
>>10793 Something like Slack? Cool.
John Titor · 2018-12-03 03:40
>>11626 turns out tail-calls in c++ are seriously unreliable for anything more then toy programs, anything less then -O3 and link time optimization and it wont work, god forbid debug mode or the like. anyway, spent a few more hours to rewrite it into a form not requiring tail-calls. i tried to do that initially, but couldnt figure out what was needed exactly. was much easier to write the recursive version first and then optimize it. i got my type-safe linear function refernce back at least.
quote · 2018-12-04 21:01
To download the images for >>11324 the images21.txt file produced in >>11393 can be processed into a command list. gawk '{printf "images_item \"%s\" \"$DIR/%s/%s/%s\"\n", $4, $2, $1, $3}' temp/images21.txt > temp/images22.txt This produces lines like the following: images_item "https://bartoszmilewski.files.wordpress.com/2014/12/initial.jpg?w=285&h=300" "$DIR/src/c05/initial.jpg" images_item "https://bartoszmilewski.files.wordpress.com/2015/08/yoneda1-e1440290035365.png?w=263&h=259" "$DIR/src/c15/yoneda1-e1440290035365.png" images_item "https://bartoszmilewski.files.wordpress.com/2014/12/initial.jpg" "$DIR/href/c05/initial.jpg" images_item "https://bartoszmilewski.files.wordpress.com/2015/08/yoneda1.png" "$DIR/href/c15/yoneda1.png" This command list can then be sourced by a shell script that defines the images_item handler. DELAY=1 images_item () { local url file url="$1" file="$2" [ -f "$file" ] && { echo "have $file" return 0 } mkdir -p "${file%/*}" echo "sleep $DELAY before $file" sleep $DELAY getdata "$url" "$file" } main_images () { local list list="$1" . "$list" } The getdata function can be any url retriever, such as one using wget. To make resuming work correctly the temporary output file becomes the real output file only upon successful completion. BR0WSER=Firefox/55.0 WGET_TIMEOUT=30 getdata () { local url dest url="$1" dest="$2" wget \ --user-agent "Mozilla/5.0 $BR0WSER" \ --server-response \ --continue --tries=0 \ --timeout=$WGET_TIMEOUT \ -O "$dest.part" "$url" mv "$dest.part" "$dest" } This method of creating a command list with a handler and then sourcing it in a script that defines the handler avoids the need for xargs, provided that the filenames are sane. It also allows the same command list to be processed by different handlers, such as switching to one using curl.
Meddler · 2018-12-06 10:20
To get the extra non-book chapters for >>11324 the link conversion step of >>11340 prints out dangling post links and the pages that reference them. This can be processed into an address list with: sed -r -e 's/^[^ ]+ -> href="([^"]+)"$/\1/' temp/links.txt | sort -u > temp/links2.txt The address list can then be looped over and items passed to some url handler. DELAY=1 url2name () { echo "$1" | gawk -v FS=/ '{print $(NF-1)}' } name2file () { echo "$DIR/$CLASS$(printf %02d $file_counter)-$1.htm" } downurlfile () { gethtmlgzip "$1" "$2" } countdir () { if [ -d "$DIR" ] then ls "$DIR" | grep -e "^$CLASS" | wc --lines else echo 0 fi } more_loopstep () { local url file url="$1" file_counter=$((file_counter + 1)) file="$(name2file "$(url2name "$url")")" echo "sleep $DELAY before $file" sleep $DELAY downurlfile "$url" "$file" } main_more () { local list line list="$1" file_counter=$(countdir) while read -r line do more_loopstep "$line" done < "$list" } The gethtmlgzip function is a variation on the getdata function of >>11684. gethtmlgzip () { local url dest url="$1" dest="$2" wget \ --user-agent "Mozilla/5.0 $BR0WSER" \ --header "Accept-Encoding: gzip" \ --server-response \ --tries=0 --timeout=$WGET_TIMEOUT \ -O "$dest.gz" "$url" [ -e "$dest" ] && rm "$dest" gzip -d "$dest.gz" }
Dox · 2018-12-07 21:06
To get the book chapters for >>11324 the list item tags from the preface can be used to generate an address list. grep -o -e '<li><a [^>]*href="[^"]*"[^>]*>[^<]*</a>' c00.htm | sed -r -e 's#^<li><a [^>]*href="([^"]*)"[^>]*>[^<]*</a>$#\1#' > temp/chapters.txt It might be tempting to match the closing list item tag for symmetry, but the last one is not closed, while the document pretends to be xhtml. The generated address list can be looped over as above and its items retrieved with the downurlfile function of >>11709. The book and non-book chapters are differentiated by the CLASS modifier of the name2file function.
Koos van der Merwe · 2018-12-11 12:38
Working on a litle roguelike demo writen using curses lib. So far I have a basic random map generator, FOV based on a Bresenham line algorithm, simple (only bump attack, deterministic damage) combat, basic AI where a monster will try to get close and attack you. The character stats consist of only HP for now. No items, not exp. levels, no skills, ... All in all I think I have a simple game (not very fun at the moment, but I can expand it). Next I will probably substitute the rand() function from the standar library with a implementation of the Mersenne Twister algorithm I'm working on right now.
Demeere · 2018-12-15 12:44
>>11505 cool domain name btw. I'm doing a single-socket util to traceroute, something like https://github.com/stacksideflow/who-sthere
Unspecified · 2019-01-01 08:39
I am working on a TUI ncurses file manager written in C with vim like keybindings. https://github.com/mananapr/cfiles I am still a novice C programmer so improvements will be appreciated
Debbie Charteris · 2019-01-25 12:37
Finished up a new version of my old crusty particle swarm library. This one is single-threaded and doesn't do any memory allocations outside of the user-provided buffer. /* See LICENSE file for copyright and license details */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include "cpso.h" char const *argv0; double rx; double ry; void usage() { fprintf(stderr, "usage: %s <number of particles> <number of iterations>\n", argv0); exit(EXIT_FAILURE); } double distance_fitness(void *arg, size_t n, double *v) { (void)arg; (void)n; return sqrt(pow(rx - v[0], 2) + pow(ry - v[1], 2)); } int main(int argc, char **argv) { size_t n_particle; size_t n_iteration; double v[3]; cpso_result g; void *buffer; cpso_config swarm; size_t seed = 213123; g.x = v; srand(time(NULL)); argv0 = argv[0]; if (argc != 3) usage(); n_particle = strtol(argv[1], NULL, 10); n_iteration = strtol(argv[2], NULL, 10); /* Set the coordinates designated "most fit" within [-5000, 5000] */ rx = 10000 * cpso_rngU01(&seed) - 5000; ry = 10000 * cpso_rngU01(&seed) - 5000; /* Set the configuration */ swarm.dim = 2; swarm.size = n_particle; swarm.b_lo = -5000; swarm.b_hi = 5000; swarm.cv = 0.8; swarm.cl = 0.1; swarm.cg = 0.2; swarm.seed = &seed; swarm.rngU01 = cpso_rngU01; swarm.arg = NULL; swarm.f = distance_fitness; /* Allocate a buffer sized for the configuration */ buffer = malloc(cpso_size(&swarm)); cpso_init(&g, buffer, &swarm); cpso_run(&g, buffer, &swarm, n_iteration); free(buffer); printf("Target position: (%f, %f) = 0\n", rx, ry); printf("Swarm results: (%f, %f) = %f\n", g.x[0], g.x[1], g.fx); return 0; }
Hitomi · 2019-01-25 15:05
>>12315 how do i learn to do things like these - i mean graphics in C, physics simulators etc
Nguoi La · 2019-01-25 16:30
>>12316 I use SDL2. If you want some example code, you can see SDL2 in action in my tetris clone: http://www.gaunt.org:8042/post/b/5.html. The download is here http://www.gaunt.org:8042/files/2018-05-05/hidamari.tar.gz.
Stallman · 2019-01-25 16:34
>>12319 i mean where did you learn this stuff - math, ai, graphics programming in C
Dox · 2019-01-25 16:38
>>12320 I read a few books, and learned math in school. The small amount of graphics programming I know is using SDL2 which is super easy to learn by just reading the docs.
x<->y · 2019-01-25 20:15
>>12319 Why was the image attached to this post deleted, may I ask?
Special Agent Bob · 2019-01-26 10:34
>>12320 For graphics programming in C I would recommend looking on the lazy foo tutorial (it' C++ but still it good): http://lazyfoo.net/tutorials/SDL/index.php
Alonzo Church · 2019-01-27 15:04
>>10903 Good job making a website lain, but you should try to use CSS to format your site. I can't run it right now, but using <br>'s is generally bad practice.
Jet Black · 2019-02-04 14:30
I'm trying to port shi-painter, a java applet, to javascript. I'm not really sure where to start with it if I'm honest.
Cereal Killer · 2019-02-06 05:35
>>12322 >>1 >Relevancy is considered very important in this board. It is expected that every image and file will be strictly relevant to programming.
Nameless · 2019-02-09 14:46
There is an "Image resize failure #111" issue on lainchan's github at https://github.com/lainchan/lainchan/issues/111 The PNG spec is RFC2083 https://tools.ietf.org/html/rfc2083 The PNG image in question has a zTXt chunk at 0x00000021 that claims a checksum of 0xE9542FE8 while having an actual checksum of 0xAE70C162, so it violates the spec. The zTXt keyword is mxGraphModel and the compressed value stream further violates the spec by using the non-standard nowrap zlib mode. The extracted mxfile is attached. It identifies itself as a product of draw.io. The invalid checksum issue is known to jgraph/drawio https://github.com/jgraph/drawio/issues/97 and it seems to be unresolved -- using the correct zlib mode and computing the correct checksum is apparently too much for some people. In conclusion, the lainchan issue can be safely closed, as it is not reasonable to expect lainchan to handle images that violate the PNG spec.
Guthrie · 2019-02-09 22:17
>>12417 I wish you luck. I feel like a cross compiler should exist somewhere.
Unknown · 2019-02-09 22:37
>>11756 good job.
Agent Richard Gill · 2019-02-11 03:26
I've been learning OpenGL from that appropriately-named ebook "Learn OpenGL". I've written simple vector-based software renderers in the past, but now I'm trying my hand at real graphics programming. The problem with the book I'm using is that it gives too much code, so I feel like a script-kiddie just copy-and-pasting soykaf into vim. To rectify that, I've been trying to experiment with things beyond where I am in the text. So far I've been able to get a triangle (and square) up on the screen. Whenever I try loading a cube, though, it just decides to silently not render anything, so I'm trying to fix that.
Unspecified · 2019-02-12 00:10
Sometimes, JS devs can be entertaining. Here's how the invalid drawio checksum >>12471 is computed. First they store the chunk data as text, including using String.fromCharCode for non-printable chars. Then they update the running checksum over the chars of their data, rather than over the bytes. To check that I am not making this up here is alderg's link from drawio issue #97: https://github.com/jgraph/drawio/blob/v7.0.2/war/js/diagramly/EditorUi.js#L5899 In the current version the file moved to https://github.com/jgraph/drawio/blob/master/src/main/webapp/js/diagramly/EditorUi.js but the checksum-relevant code has not changed. Here is the chunk assembly: var chunkData = key + String.fromCharCode(0) + ((type == 'zTXt') ? String.fromCharCode(0) : '') + value; // FIXME: Wrong crc var crc = 0xffffffff; crc = this.updateCRC(crc, type, 0, 4); crc = this.updateCRC(crc, chunkData, 0, chunkData.length); result += writeInt(chunkData.length) + type + chunkData + writeInt(crc ^ 0xffffffff); and the updateCRC function: EditorUi.prototype.updateCRC = function(crc, data, off, len) { var c = crc; for (var n = 0; n < len; n++) { c = EditorUi.prototype.crcTable[(c ^ data[off + n]) & 0xff] ^ (c >>> 8); } return c; }; So obviously what will happen is that, when asked to xor a number and a character, JS will try to parse the character as a number and will replace everything that is not a digit with 0. And it will do this silently, since JS devs are obviously smart enough to know what they're doing and don't need type help from the runtime. The effect is that nearly all information from the input bytes is lost, by performing the translation 49->1 ... 57->9 else->0. This can be used to replicate the fake checksum of the zTXt chunk of the PNG image from drawio issue #97. $ hd dio97.png 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 03 17 00 00 00 8d 08 06 00 00 00 c5 35 87 |..............5.| 00000020 84 00 00 02 85 7a 54 58 74 6d 78 47 72 61 70 68 |.....zTXtmxGraph| 00000030 4d 6f 64 65 6c 00 00 35 53 d9 ae 9b 30 10 fd 1a |Model..5S...0...| [...] 000002a0 72 fe df ba ef 15 24 fa bf 3f c4 aa 7f 01 63 82 |r.....$..?....c.| 000002b0 d9 ac 00 00 11 56 49 44 41 54 78 9c ed dd 4f 4c |.....VIDATx...OL| [...] To get the fake checksum on a working CRC32 implementation the information loss step has to be performed manually, as preprocessing. >>> with open ('dio97.png', 'rb') as f: ... b = f.read () ... >>> z = b [33 + 4 : 33 + 4 + 4 + 645] >>> z [:32] b'zTXtmxGraphModel\x00\x005S\xd9\xae\x9b0\x10\xfd\x1a\xa4\xf6\xa1\x11\x98' >>> table = [0] * 256 >>> for k in range (10): ... table [ord (str (k))] = k ... >>> ztab = bytes (table [k] for k in z) >>> import zlib >>> x = zlib.crc32 (ztab) >>> '0x{:08X}'.format (x) '0x6382D9AC' This explains the checksum of this chunk. However, applying the same process to the zTXt chunk of the PNG image from lainchan issue #111 yields 0x6C8FB0E9, while the in-file fake checksum is 0xE9542FE8. $ hd lain111.png 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 04 4c 00 00 06 29 08 06 00 00 00 4c a7 89 |...L...).....L..| 00000020 7a 00 00 15 8a 7a 54 58 74 6d 78 47 72 61 70 68 |z....zTXtmxGraph| 00000030 4d 6f 64 65 6c 00 00 4d 79 c7 0e a4 4c d0 e4 d3 |Model..My...L...| [...] 000015b0 73 ff 03 e9 54 2f e8 00 00 20 00 49 44 41 54 78 |s...T/... .IDATx| [...] To explain this we have to dig a little deeper. Since the current checksum code is still the one from v7.0.2, perhaps it changed before that. Indeed, looking through the change history of EditorUi.js there is a crc change from v6.3.5 to v6.3.6 in commit abf9e41ea6123a53a5c7a7ddf16dd6ebdf47c71a by alderg on Mar 16 2017: https://github.com/jgraph/drawio/commit/abf9e41ea6123a53a5c7a7ddf16dd6ebdf47c71a#diff-95a5119709e841b5ece358adc05619e0 For some reason alderg didn't mention this crc change in the ChangeLog. Up to v6.3.5 the chunk assembly looked like this: https://github.com/jgraph/drawio/blob/v6.3.5/war/js/diagramly/EditorUi.js#L5481 var crc = 0xffffffff; crc = this.updateCRC(crc, type, 0, 4); crc = this.updateCRC(crc, value, 0, value.length); result += writeInt(key.length + value.length + 1 + ((type == 'zTXt') ? 1 : 0)) + type + key + String.fromCharCode(0) + ((type == 'zTXt') ? String.fromCharCode(0) : '') + value + writeInt(crc ^ 0xffffffff); So the checksum was over the tag and the value part of the zTXt payload, instead of the tag and the full zTXt payload. This can be used to replicate the fake checksum from #111, by skipping the keyword, the separator and the compression byte. >>> with open ('lain111.png', 'rb') as f: ... b = f.read () ... >>> z = b [33 + 4 : 33 + 4 + 4 + 5514] >>> z [:32] b'zTXtmxGraphModel\x00\x00My\xc7\x0e\xa4L\xd0\xe4\xd3\x8c\xb4{\xd8O' >>> zcut = z [:4] + z [18:] >>> zcut [:32] b'zTXtMy\xc7\x0e\xa4L\xd0\xe4\xd3\x8c\xb4{\xd8Oxs\xc4{\xef\xb9\xe1\xbd\xb7\xcd\xd3\xff0\xb3' >>> ztab = bytes (table [k] for k in zcut) >>> x = zlib.crc32 (ztab) >>> '0x{:08X}'.format (x) '0xE9542FE8' This explains the checksum of #111. It also shows that when barrucadu opened #111 on Jun 15 2017, the code that generated that version of the fake checksum was already three months out of date. As for the drawio checksum, while fixing the crc to use the bytes extracted from the string rather than the chars will still leave the zlib issue, it will at least make the images usable by those decoders that do not care to look inside the zTXt payload and only check the structural integrity of the PNG. And to put things into perspective, here is the drawio developers' understanding of their own code, from #97: """We've had a thorough look at the function for the CRC in JS but didn't find a fix. The same code works in Java so we could use some help here, guys...""" and """I'm changing approach on handling issues. Basically, I want PRs rather than reports. Issues without a PR in A reasonable time will be closed."""
Jean Dupont · 2019-02-12 20:25
A mercury tutorial --- Birds & Bread --- Any thing which likes bread is a bird. likes_bread(X) :- bird(X). But which birds? bird(swan). bird(cardinal). bird(raven). So do they all like bread? ?- likes_bread(X). X = swan. X = cardinal. X = raven. Do only birds like bread? No! People do too. people(anna). people(bert). people(cassy). But not Bert. likes_bread(X) :- bird(X); people(X), not(X = bert). So does cassy like bread? ?- likes_bread(cassy). yes. Swans? ?- likes_bread(swan). yes. And Bert? ?- likes_bread(bert). no. Because Bert is special. --- Append & Lists --- To append an empty list with a list is the same as just that list. append([], Ys, Ys). To append a list of one element or more we append the rest of the list then add the the element we took of back to it. append([X | Xs], Ys, Zs) :- append(Xs, Ys, Z0), Zs = [X | Z0]. Joining two lists. ?- append([1,2], [3,4], X). Results in a combined list of the contents. X = [1,2,3,4]. where. input | ,- input v v append([1,2], [3,4], X). <- output If we have a result and one of the inputs. ?- append(X, [3,4], [1,2,3,4]). We can figure out the other input. X = [1,2]. Where. output | ,- input v v append(X, [3,4], [1,2,3,4]). <- input But if we only know the result. ?- append(X, Y, [1,2,3,4]). Then we get all possible inputs. X = [] Y = [1,2,3,4] X = [1] Y = [2,3,4] X = [1,2] Y = [3,4] X = [1,2,3] Y = [4] X = [1,2,3,4] Y = [] Where. output | ,- output v v append(X, Y, [1,2,3,4]). <- input Since each query tries to make both sides equal. The following equations are the same as the above. [1,2] ++ [3,4] = X X ++ [3,4] = [1,2,3,4] X ++ Y = [1,2,3,4] But why didn't we try any like this. ?- append(X, [2,3], Y). ?- append([1,2], X, Y). ?- append(X, Y, Z). Because there's an infinite number of solutions for them! Try it out on paper and see for now as we'll nead features we haven't covered yet to inspect them.
Knuth · 2019-02-13 13:25
>>12507 I think you should describe in more detail what the commands you enter do exactly. I understand what is happening(at least I think I do) but only because I used to play with Prolog in the past. A little intro about logical programming also would be in order as I think it's not a well known subject. Also it's not entirely visible what parts of the text are comments, what are code entered, and what are the output of the program (like I guess this: "Swans?" is a comment, this: "?- likes_bread(swan)." is a part of the code, and this: "yes." is the output of the program but I'm guessing all that). You also didn't write anything about the syntax of the language. I'm pointing this not because I want to attack you (I think it's great that you want to make a tutorial) but because I would like you to put yourself in the boots of the reader. If this is really a tutorial for others to learn from than there is a big chance that the reader won't know anything about this language (yet), and obvious things for you (like the correct syntax) could not be so obvious for the reader. I never gone to far in learning Prolog so I would like to ask what are the benefits/uses of logical languages? I think I read that thay used Prolog to creat the AI in F.E.A.R but thats about it.
Drano · 2019-02-13 14:48
The explanation for the zlib mode >>12471 turns out to be quite simple. In EditorUi.js >>12500 writeGraphModelToPng performs the crc and the chunk assembly. It is called with its 'value' parameter set to atob(this.editor.graph.compress(xml)) Compress lives in https://github.com/jgraph/drawio/blob/v7.0.2/war/js/mxgraph/Graph.js It uses pako to handle compression https://github.com/nodeca/pako and it calls pako.deflateRaw. The decompress function calls pako.inflateRaw. So drawio explicitly asks for the nowrap mode when compressing and expects it when decompressing. If drawio were the exclusive producer and consumer of these zTXt chunks with mxGraphModel values this wouldn't be a problem, since it expects to receive what it produced. Nevertheless, zTXt is a standard chunk and the PNG spec section "4.2.10. zTXt Compressed textual data" states: """The compression method byte is followed by a compressed datastream that makes up the remainder of the chunk. For compression method 0, this datastream adheres to the zlib datastream format (see Deflate/Inflate Compression, Chapter 5).""" and in "5. Deflate/Inflate Compression": """Deflate-compressed datastreams within PNG are stored in the "zlib" format, which has the structure: Compression method/flags code: 1 byte Additional flags/check bits: 1 byte Compressed data blocks: n bytes Check value: 4 bytes [...] PNG also uses zlib datastreams in zTXt chunks. In a zTXt chunk, the remainder of the chunk following the compression method byte is a zlib datastream as specified above.""" So as a point of correctness, using the nowrap mode in zTXt violates the PNG spec.
Hopper · 2019-02-15 10:34
There is a "Can't rebuild #140" issue at https://github.com/lainchan/lainchan/issues/140 >Undefined index: recent_count in /var/www/html/templates/themes/semirand/theme.php at line 46 That theme.php uses recent_count but its info.php uses bumped_count. https://github.com/lainchan/lainchan/tree/master/templates/themes/semirand Either change recent_count to bumped_count in one billion places, or change bumped_count to recent_count in the $theme['config'] of info.php. The name mismatch is there from the initial commit 7c6eef81c55d6f5ccfa6ebba759afcec7b79115d by mgrabovsky on Jun 2 2015 https://github.com/lainchan/lainchan/commit/7c6eef81c55d6f5ccfa6ebba759afcec7b79115d#diff-243d858e5639d5ae30a260e9d0d31ccc
William Holtzer · 2019-02-21 10:27
"Bans are impossible under PHP 7.1 #141" https://github.com/lainchan/lainchan/issues/141 """However, on my server, I run into another error. This error is thrown whenever a member of staff tries to place a non-permanent ban: A non-numeric value encountered in /documentroot/inc/bans.php at line 50 On my server, I am running PHP 7.1.13-1. It seems that new behavior was introduced in this version, causing the error: https://stackoverflow.com/questions/42044127/warning-a-non-numeric-value-encountered """ https://github.com/lainchan/lainchan/blob/master/inc/bans.php#L50 if (!preg_match('/^((\d+)\s?ye?a?r?s?)?\s?+((\d+)\s?mon?t?h?s?)?\s?+((\d+)\s?we?e?k?s?)?\s?+((\d+)\s?da?y?s?)?((\d+)\s?ho?u?r?s?)?\s?+((\d+)\s?mi?n?u?t?e?s?)?\s?+((\d+)\s?se?c?o?n?d?s?)?$/', $str, $matches)) return false; $expire = 0; if (isset($matches[2])) { // Years $expire += $matches[2]*60*60*24*365; } Since the += is reached, the isset test passes. Isset checks whether a variable is set and not NULL. http://php.net/manual/en/function.isset.php Since $matches[2] is a (\d+) group, it must be numeric if it matches. Therefore, there was a $matches[2] that did not match but passed the isset test, so it was set and not NULL. At this point it is worth checking how preg_match reports unmatched groups, despite any assumption one might have about sane behavior. http://php.net/manual/en/function.preg-match.php """PREG_UNMATCHED_AS_NULL If this flag is passed, unmatched subpatterns are reported as NULL; otherwise they are reported as an empty string.""" So an unmatched $matches[2] is set as the empty string, passes isset, and is then caught as non-numeric. The manual states that PREG_UNMATCHED_AS_NULL is supported from 7.2.0, so that would bump up the version requirement. To avoid that, the group should be checked for being an empty string. And since in this case isset is only called with valid indices of $matches, it will always be true so it can be removed as a test. In vichan they muted rather than fixed the error by casting the empty string to int. https://github.com/vichan-devel/vichan/issues/301 https://github.com/vichan-devel/vichan/commit/524d48110ba7201adaaf314750deb9b6b4edc2cf#diff-bd1dde787ae46086e40901b77a24f118 Also, the regexp is missing the optional space between days and hours, and using the possessive \s?+ is pointless in this case. >>> import itertools >>> flatten = itertools.chain.from_iterable >>> forever = itertools.repeat >>> data = "y.ears mo.nths w.eeks d.ays h.ours m.inutes s.econds" >>> s = r'\s?'.join (map (lambda unit: (lambda left, right: r'((\d+){}{})?'.format (left, ''.join (flatten (zip (right, forever ('?')))))) (* unit.split ('.')), data.split ())).join (('/^', '$/')) >>> print (s) /^((\d+)ye?a?r?s?)?\s?((\d+)mon?t?h?s?)?\s?((\d+)we?e?k?s?)?\s?((\d+)da?y?s?)?\s?((\d+)ho?u?r?s?)?\s?((\d+)mi?n?u?t?e?s?)?\s?((\d+)se?c?o?n?d?s?)?$/
Roger Pollack · 2019-02-22 00:25
#140 diff --git a/templates/themes/semirand/info.php b/templates/themes/semirand/info.php index 255935c..8590a20 100644 --- a/templates/themes/semirand/info.php +++ b/templates/themes/semirand/info.php @@ -53,7 +53,7 @@ ), array( 'title' => 'Bumped threads', - 'name' => 'bumped_count', + 'name' => 'recent_count', 'comment' => '(number of consecutive recent threads)', 'type' => 'text', 'default' => '1',
Joe Bloggs · 2019-02-22 00:33
#141 diff --git a/inc/bans.php b/inc/bans.php index 7a514f0..6f109b3 100644 --- a/inc/bans.php +++ b/inc/bans.php @@ -40,36 +40,36 @@ class Bans { if (($time = @strtotime($str)) !== false) return $time; -if (!preg_match('/^((\d+)\s?ye?a?r?s?)?\s?+((\d+)\s?mon?t?h?s?)?\s?+((\d+)\s?we?e?k?s?)?\s?+((\d+)\s?da?y?s?)?((\d+)\s?ho?u?r?s?)?\s?+((\d+)\s?mi?n?u?t?e?s?)?\s?+((\d+)\s?se?c?o?n?d?s?)?$/', $str, $matches)) +if (!preg_match('/^((\d+)\s?ye?a?r?s?)?\s?((\d+)\s?mon?t?h?s?)?\s?((\d+)\s?we?e?k?s?)?\s?((\d+)\s?da?y?s?)?\s?((\d+)\s?ho?u?r?s?)?\s?((\d+)\s?mi?n?u?t?e?s?)?\s?((\d+)\s?se?c?o?n?d?s?)?$/', $str, $matches)) return false; $expire = 0; -if (isset($matches[2])) { +if (!empty($matches[2])) { // Years $expire += $matches[2]*60*60*24*365; } -if (isset($matches[4])) { +if (!empty($matches[4])) { // Months $expire += $matches[4]*60*60*24*30; } -if (isset($matches[6])) { +if (!empty($matches[6])) { // Weeks $expire += $matches[6]*60*60*24*7; } -if (isset($matches[8])) { +if (!empty($matches[8])) { // Days $expire += $matches[8]*60*60*24; } -if (isset($matches[10])) { +if (!empty($matches[10])) { // Hours $expire += $matches[10]*60*60; } -if (isset($matches[12])) { +if (!empty($matches[12])) { // Minutes $expire += $matches[12]*60; } -if (isset($matches[14])) { +if (!empty($matches[14])) { // Seconds $expire += $matches[14]; }
Anonymous · 2019-02-22 00:37
inc/bans.php uses tabs
Knuth · 2019-02-22 04:22
I'm working on a small script that will notify me when the bus is approaching the stop where I want to get off. On Oahu it's really hard to tell where the bus actually is, especially at night, and they don't call out the names of the next stop unless someone has pulled the stop cable. I have learned that the HEA api is only barely compliant with Google's GTFS standard and not nearly as robust as I initially believed. I can't figure out how to relate the ID of a bus to the next stop on its route. To circumvent this, I'm just copy/pasting the stop coordinates from google maps into my script. I finished writing up the bits which actually query the honolulu estimated arrivals API, now I just need to write some kind of listener which will query the api periodically and calculate the bus's distance from the destination. Not sure what interval is best, but I think 30 seconds is a good start. Bus drivers can decide not to call home to report their location so there is no reliable interval to update. import xml.etree.ElementTree as ET import urllib as http # returns my api key for the Honolulu Estimated Arrivals API def getAPIKey(): keyFile = open('apiKey', 'r') key = keyFile.read() keyFile.close() return key # returns an xml element tree containing latitude, longitude, driver ID, etc, for a given busID def getBusData(busID): endpoint = 'http://api.thebus.org/vehicle/?key=' + getAPIKey() + '&num=' + busID data = http.urlopen(endpoint) return ET.fromstring(data.read()) def getBusLat(busData): return busData[1][3].text def getBusLon(busData): return busData[1][4].text class Bus: def __init__(self, busID): self.busID = busID self.busData = getBusData(busID) def updateData(self): self.busData = getBusData(self.busID) def getBusPos(self): return getBusLat(self.busData), getBusLon(self.busData) # Create a bus object for bus no. 187 b = Bus('187')
Zero Cool · 2019-02-22 05:15
>>12645 Living in one of those places where buses and the companies operating them give basically no useful data, I had the idea of implementing a simple GPS distance check with average speed over the last X minutes. Perhaps that may be an option?
aliased · 2019-02-22 07:29
>>12648 That would be an option for you, as long as you know where you are getting off the bus.
Aristóteles Amadópulus · 2019-02-22 21:17
I'm working on a client for Neocities' api written in C. It maps json responses to predefined structs. It's around 700 lines long excluding the examples and a library I included for parsing dates. It uses libcurl and libjson-c. The error handling is everywhere; there are no mem leaks so far. It supports info, list, upload and key. If someone is interested i'd happily provide a link.
John Titor · 2019-02-22 21:23
>>12653 Forgot the example for the info call c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> #include <json.h> #include "dtparser.h" #include "neocities.h" int main(int argc, char *argv[]) { neocities_res res; int i, err; char date_ca[33] = { 0 }; char date_lu[33] = { 0 }; if (argc != 1 && argc != 2) { fprintf(stderr, "Usage: %s [sitename]\n", argv[0]); exit(200); // no enum member share this number } if (curl_global_init(CURL_GLOBAL_SSL) != 0) return NEOCITIES_LLVL_ERR_CURL_GLOBAL_INIT; if ((err = neocities_api_ex(APIKEY, info, ((argc == 1) ? "" : argv[1]), &res)) != NEOCITIES_LLVL_OK) return err; if (res.data.info.sitename != NULL) printf("sitename %s\n", res.data.info.sitename); /* -1 is the default for uninitialized numbers; in case they are missing for the json response */ if (res.data.info.views != -1) printf("views %d\n", res.data.info.views); if (res.data.info.views != -1) printf("hits %d\n", res.data.info.hits); /* 0 is the default for uninitialized dates */ if (res.data.info.created_at != 0) { rfc5322_date_create(res.data.info.created_at, date_ca, 32); printf("created_at %s\n", date_ca); } if (res.data.info.last_updated != 0) { rfc5322_date_create(res.data.info.last_updated, date_lu, 32); printf("last_updated %s\n", date_lu); } if (res.data.info.domain != NULL) { printf("domain %s\n", res.data.info.domain); } if (res.data.info.tags[0] != NULL) { printf("tags ["); i = 0; while (res.data.info.tags[i + 1] != NULL) { printf("\"%s\", ", res.data.info.tags[i]); i++; } printf("\"%s\"]\n", res.data.info.tags[i]); } neocities_destroy(&res); curl_global_cleanup(); return 0; }
HELIOS · 2019-02-22 23:22
>>12655 Try #Python :)
Yu-ichi · 2019-02-23 00:38
>>12653 I'd love a link to it, please!
Anonymous · 2019-02-23 02:16
>>12656 Yeah, i've done it for the sake of doing something in C >>12657 here ya go https://git.soykaf.me/neocities.h/log.html or https://github.com/jennydoe/neocities.h plz tell me it ain't so bad
sage · 2019-02-24 08:52
>>12657 So what do you think ?
pop · 2019-02-27 00:12
https://github.com/lainchan/lainchan/issues/141 """Appleman1234 commented Feb 26, 2019 Fixed as per dce8a6e""" https://github.com/lainchan/lainchan/commit/dce8a6e1ec82b876d217418672f16e5765f66c43 """Casting to make bans work with newer PHP, as per vichan Appleman1234 committed Feb 26, 2019""" if (isset($matches[2])) { // Years - $expire += $matches[2]*60*60*24*365; + $expire += (int)$matches[2]*60*60*24*365; }
protected · 2019-03-01 08:30
Does anyone have the link the Lainon's (I think it was his) webpage where you had a weird assembly debugger and you had to crack a puzzle before being redirected? It was posted here about a year or two ago
Liet Kynes · 2019-03-01 09:29
>>12717 http://skullcode.com/ Do you mean this?
Cowboy · 2019-03-01 18:20
>>12718 That's it! Thank you, anon.
setq · 2019-03-01 20:52
https://github.com/jgraph/drawio/commit/4c523397cde08db540ee6e99210291c106450d0f#diff-84c7eaa80e7554c058de9ed854661d93 """10.2.9 release alderg committed Feb 28, 2019""" ChangeLog 28-FEB-2019: 10.2.9 - Moves Confluence Cloud viewer settings to format panel - Allows all content from docs.google.com via proxy - Adds menu for moving selection to other layers - Adds simple viewer option for Confluence Cloud - Fixes bad CRC in PNG exports src/main/webapp/js/diagramly/EditorUi.js for (var n = 0; n < len; n++) { - c = EditorUi.prototype.crcTable[(c ^ data[off + n]) & 0xff] ^ (c >>> 8); + c = EditorUi.prototype.crcTable[(c ^ data.charCodeAt(off + n)) & 0xff] ^ (c >>> 8); }
list · 2019-03-01 22:43
I recently got really into Python's asyncio so I'm actually making an alternative imageboard using it. The stack is a Quart server and a Tortoise ORM, maybe later a nginx proxy serving static files. The main difference from the regular imageboards is that when you're in a thread, the client negotiates a websocket with the server, so any new posts you make get sent through it and broadcasted to everyone connected to that thread in real time instead of polling like a moron. You only use regular HTTP on other pages, in a thread it's like you're in a chatroom. Since I'm not a frontend developer I have essentially zero CSS, but I'm fine with slow burning that. I'm more concerned with ensuring proper transactional support and ensuring everything runs fine in an asynchronous way. Something I also want to try is reducing JS dependencies, it's ridiculous - press F12 and see how many files are getting fetched by this page.
Hagbard Celine · 2019-03-05 15:05
"Enabling file-selector.js, results in files posted in replies not being uploaded successfully. #116" https://github.com/lainchan/lainchan/issues/116 """Enabling file-selector.js, results in files posted in replies not being uploaded successfully. Files in new posts are posted without issues. Currently this is being worked around by having file-selector.js disabled.""" https://github.com/lainchan/lainchan/blob/master/js/file-selector.js While this is a JS issue and thus does not affect me, here are some thoughts. It seems curious that every file in the 'paste' handler is assumed to be a PNG image, rather than checking the type property of items[i]. for (var i=0; i<clipboard.items.length; i++) { if (clipboard.items[i].kind != 'file') continue; //convert blob to file var file = new File([clipboard.items[i].getAsFile()], 'ClipboardImage.png', {type: 'image/png'}); addFile(file); } The files are added to the form data with the field names 'file', 'file2' ... 'fileN'. And since this is written by webdevs, the break test is only done after the key computation. $(document).on('ajax_before_post', function (e, formData) { for (var i=0; i<max_images; i++) { var key = 'file'; if (i > 0) key += i + 1; if (typeof files[i] === 'undefined') break; formData.append(key, files[i]); } }); The problem is that if these field names are not whitelisted in $config['spam']['valid_inputs'], anti-bot.php will use them in the hash verification and will declare the post to be spam. https://github.com/lainchan/lainchan/blob/master/inc/anti-bot.php // Reconsturct the $inputs array $inputs = array(); foreach ($_POST as $name => $value) { if (in_array($name, $config['spam']['valid_inputs'])) continue; $inputs[$name] = $value; } These file fields are not whitelisted in inc/config.php, so if they are also missing from instance-config.php or board-specific config.php files, which are not on github, it would be very surprising if non-mods could avoid the spam judgement with file-selector.js. https://github.com/lainchan/lainchan/blob/master/inc/config.php // Always update this when adding new valid fields to the post form, or EVERYTHING WILL BE DETECTED AS SPAM! $config['spam']['valid_inputs'] = array( 'hash', [...] 'tag' ); Adding them to the global config would make the most sense. As for the specific no upload issue, here is one scenario in which it will occur. Files are kept in a private 'files' variable and only added to the outgoing form data in the handler for 'ajax_before_post'. The event is only triggered in a form submit handler installed by the setup_form function of js/ajax.js. https://github.com/lainchan/lainchan/blob/master/js/ajax.js If this event is not triggered file-selector.js will not add its files to the outgoing form data, and the situation will be silently equivalent to not selecting any files for upload. If setup_form is not called for a file upload form, 'ajax_before_post' will not trigger and file-selector.js will not upload files. Setup_form is called for the original post from in js/ajax.js's handler for $(window).ready, and for the quick-reply form in js/ajax.js's handler for 'quick-reply'. The 'quick-reply' event is triggered in the show_quick_reply function of js/quick-reply.js. https://github.com/lainchan/lainchan/blob/master/js/quick-reply.js Show_quick_reply is called when the 'Quick Reply' button is clicked, as well as in js/quick-reply.js's handler for 'cite'. The 'cite' event is triggered in the citeReply function of templates/main.js. https://github.com/lainchan/lainchan/blob/master/templates/main.js One of the callers of citeReply is the rememberStuff function of templates/main.js when the URL has a #qNNN fragment. This fragment can be obtained by clicking a post number in the index pages. if (window.location.hash.indexOf('q') == 1) citeReply(window.location.hash.substring(2), true); The rememberStuff function is called unconditionally by templates/post_form.html right after the original post form's closing tag. https://github.com/lainchan/lainchan/blob/master/templates/post_form.html Therefore, if a posting page is reached with an URL with a #qNNN fragment, the following chain of steps will occur: rememberStuff -> citeReply -> 'cite' event -> show_quick_reply -> 'quick-reply' event Here's the important bit: this will occur right after the original post form's closing tag, but js/ajax.js will not even register its 'quick-reply' handler until the time of $(window).ready. But that handler is needed to run setup_form on the quick reply form, without which there will be no 'ajax_before_post' event and file-selector.js will not upload files from the quick reply form. The simplest solution is to have two logical sections in js/ajax.js, one that executes at the time of the head section and one that executes at the time of the 'ready' event. The registration of the 'quick-reply' handler, along with its dependencies, should be moved from the latter to the former, so that it is in place by the time the rememberStuff chain triggers the 'quick-reply' event. You can see how to do this in js/quick-reply.js, which takes care to register its 'cite' handler at the time of the head section. These are some of the things that need to be fixed for file-selector.js to work.
Appleman1234 · 2019-03-05 20:40
>>12759 Whilst I appreciate the analysis. I have two questions ? Why post this here and not in Github comment on the issue ? Why not submit a patch or pull request ? Most of the information you post I am already aware of and have already tried various attempts to resolve the issues in question.
Unnamed · 2019-03-06 00:58
>>12766 >Why post this here and not in Github comment on the issue ? Interacting with that site seems to require creating an account as well as enabling remote code execution, which I am not inclined to do. I already have, here, a communication channel that requires neither. The bottom of the #116 page states >Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment so either anonymous comments have been disabled, or the site does not have this option to begin with. Furthermore, by posting here the explanation probably reaches a wider readership than on the issue page -- e.g. the explanation for drawio #97 had no problem reaching the drawio people. Some of the Lains who did not yet think about contributing to lainchan might see that the barrier to contribution is lower than they might have thought. For example, adding the file name fields to $config['spam']['valid_inputs'] presents no particular difficulty. This might encourage more Lains to contribute. >Why not submit a patch or pull request ? A pull request has the same problem of interacting with the site as outlined above. I am also not at an age where I need to chase PRs. As for a patch, for one thing I do not have a working local copy of lainchan while others do, so they are in a much better position to submit a patch they have tested. And for another, I am unsure how much good posting a patch would do, given the fact that I posted the explanation and patch for #141 further up the thread, but on github the technically inferior vichan workaround was chosen over the proper solution of replacing isset with !empty. >Most of the information you post I am already aware of and have already tried various attempts to resolve the issues in question. It is perfectly normal that several people would be looking into the open issues. However, the only information at my disposal is that #116 has been labeled a bug for twenty months, and during that time those who obviously already have accounts and have no objection to interacting with the site have not posted any progress update, which is why I ventured to post a detailed explanation. Since the issue remained open, I assume your "various attempts to resolve the issues in question" did not work. Knowing about what has already been tried and did not work would be valuable for the rest of us looking into the same issue. You would be helping us all out by describing your attempts, in either venue.
Hagbard Celine · 2019-03-06 05:18
>>12766 >Why post this here and not in Github comment on the issue ? A significant portion of the people here are the type to self host a Github alternative.
Cypher · 2019-03-08 03:54
The following test can be performed on this site within the context of >>12759 for file-selector.js. Temporarily enable scripts from the lainchan.org domain if they are disabled, then click on a post number in an index page to enter a posting page with a #qNNN fragment. An example for this thread would be: https://lainchan.org/%CE%BB/res/10399.html#q10399 This will show the quick reply box. Add the file selector script by entering: var script = document.createElement ('script'); script.src = 'https://lainchan.org/js/file-selector.js'; document.head.appendChild (script); Once the script is loaded, perform the initialization normally performed by post_form.html: https://github.com/lainchan/lainchan/blob/master/templates/post_form.html init_file_selector (3); At this point the form may not look exactly like it normally would because the order of the clone() call from quick-reply.js and init_file_selector() is reversed. Next, fire the 'quick-reply' event so that ajax.js will run its handler and call setup_form on the quick reply form: $(window).trigger ('quick-reply'); This is needed because ajax.js missed the original 'quick-reply' event as explained previously, so there would have been no 'ajax_before_post' event at post time. Finally, drag a test file of a few bytes onto the drop zone and post. This procedure resulted in a successful file upload on the test board, using file-selector.js with the quick reply box. This shows that either the antibot check is disabled, even though its fields are present, or the fileN field names that are not whitelisted in inc/config.php are included in one of the config files that is not on github. It should be easy to tell the two situations apart -- it's most likely the latter. Another consequence is that the analysis of >>12759 with regard to the timing of the 'quick-reply' handler registration is confirmed.
array · 2019-03-08 20:56
A correction to >>12759 and >>12782. It was pointed out to me by a colleague who is more knowledgeable about webdev matters that posted files are only present in $_FILES, rather than in both $_POST and $_FILES, even though they are fields of the post form. This means that the input collection loop from the hash verification of anti-bot.php, which iterates $_POST, already has the files filtered out. This is convenient since there is no way to precompute the hash of future content in the hash generation phase, and there is no need to add the names of the file fields to the whitelisting $config['spam']['valid_inputs'] arrays. The point about the successful posting experiment stands.
Wirth · 2019-03-09 14:34
A second successful upload test with a modified procedure. A posting page is entered with scripts enabled but without a #qNNN fragment, so the quick reply box is not shown yet. File-selector.js is loaded and initialized as in >>12782. The 'quick-reply' event is not fired manually. Clicking a post number brings up the quick reply box. Because ajax.js has its 'quick-reply' handler registered by this time, setup_form has been run when the quick reply box came up. A subsequent file drag and post combo results in an uploaded file. This shows that the handler registration timing is not only necessary, it also seems to be sufficient. With that in mind, here's a new ajax.js that implements the changes explained in >>12759. It is untested because I do not have a working local copy of lainchan. Perhaps someone who does would be kind enough to test it. Once it is seen to work this should resolve #116.
Tank · 2019-03-10 09:28
Anyone has an interesting programming idea for a college project? In my country, you have to make a 1-year project to finish your degree. I have no idea what to do, ive changed it 2 times already. I like programming in general from functional to low-level (altough im more proficient on high-level ones anything above asm), security is also a topic ive an interest.
list · 2019-03-10 10:19
>>12800 1 year might be enough to make an operating system and maybe a programming language to write its standard library in.
Boole · 2019-03-10 15:23
>>12800 >ive changed it 2 times already Maybe tell us what you tried already and why you droped the idea. That way it will be easer for us to give you some guidence.
JARGON · 2019-03-10 21:43
>>12801 That seems interesting. I`ve been thinking on working with something around Minix or LFS. Functional prog is cool as hell, but ive no idea what to do with it. >>12804 My first 2 ideas were: - Algotrading, I found ML fascinating on first, but i dont like it as much as programming, SO and security. Ill probably mess with it later but i decided to not work with it for now. Also, my background in math really is like kicking dead whales down the beach. - Use public political data to make some website/app around it where ppl could access politicians and govt projects data. There were already an API for it and some apps created around it using the API. So I dropped it, even though I might create a website with it on a side project since i wont need write an entire scientific paper around it as its required by the college proj.
Eldon Tyrell · 2019-03-11 00:16
>>12806 >>12800 Microkernel OS in Haskell? It's been done before: http://programatica.cs.pdx.edu/House/ I've been thinking about a microkernel where everything - from IPC to networking and graphics - is based on functional reactive programming with security based on type-restricted effects. It would be a good way to merge high- and low-level programming while also addressing security.
Delilah · 2019-03-11 08:14
>>12800 Make a web browser that uses any scripting language as a client side language, should be not so hard.
car · 2019-03-11 12:40
>>12800 A few ideas: - A basic databased - Some programming tool (Version control or some form of source analizer). - IRC server - Raytracer engine (this is maybe a litle heavy on math) - Emulator for some old console
Unnamed · 2019-03-13 04:07
https://github.com/lainchan/lainchan/issues/114 "auto-reload.js problems #114" https://github.com/lainchan/lainchan/blob/master/js/auto-reload.js Some notes at a glance: - The makeIcon('reply') invocation will set the shortcut icon to /static/favicon-reply.ico, which is currently a 404. - MakeIcon is only used in auto-reload.js so there is no need to clutter the global scope with it. - The dothis function called by the submit handler doesn't seem to be defined.
Gyula Kovacs · 2019-03-13 12:42
>>12807 I might want to check it out. My prof. coordinator is a Haskell teacher, so perhaps, he might help me with it. I`ll give it a peek and send him an email about it. Thanks! >>12808 Not sure if I get it, tell me if I got it right. Like a browser using python as it were js? >>12809 IRC server and emulator both sound cool. Ive been wanting to work with IRC for ages now but I never did stop what I was doing to work with it. Emulator programming seems cool because of the low level programming involved. Ill put it on the list, search about it, and see if i can make a proj with it.
vector · 2019-03-13 14:51
The new post insertion in auto-reload.js >>12829 is wrong. if ($("div.post").length > 1){ $(this).parent().insertAfter($('div.post:not(.post-hover):last').parent().next()).after('<br class="clear">'); } else { $(this).insertAfter($('div.post:not(.post-hover):last')).after('<br class="clear">'); } The structure of div.thread in a thread page without JS is defined by templates/post_thread.html, templates/post_reply.html and templates/post. It looks like this: a.post_anchor div.files div.post.op repeat ( div.postcontainer <br/> ) for every reply <br class="clear"/> <hr/> https://github.com/lainchan/lainchan/blob/master/templates/post_thread.html https://github.com/lainchan/lainchan/blob/master/templates/post_reply.html One issue is that the 'after' calls should use '<br/>' as used by templates/post_reply.html. The '<br class="clear"/>' is only used once by templates/post_thread.html, to separate the horizontal rule / thematic break, and it would have lacked the closing slash anyway. More importantly, the else branch inserts the wrong element. It inserts the div.post.reply instead of the div.postcontainer, which is its .parent(). And while the insertion point is correct, right after the only div.post, that :last can be removed and an .op class added before the :not, which will be faster. The effect of inserting the wrong element, div.post.reply, is that the next insertion, which will take the first branch, will find that the last reply's .parent() is the div.thread, the .next() is the div.thread-interactions, and will insert after that, completely outside the reply list. This is the mechanism by which replies can end up under the separator line. This effect can be deterministically replicated by the following procedure. - Go to a thread with a small number of replies, not less than two, with scripts enabled. E.g. >>12786 - Uncheck the auto update box. - Inspect the page and delete the div.postcontainer elements and the br elements immediately following each one, leaving only the op. - Click '[Update]'. You will see the replies from the second onward go under the reply area, below the separator and some links. Inserting the .parent() on the else branch will fix this.
array · 2019-03-13 21:57
For some light entertainment, the >>12838 test can be performed on a thread with a large number of replies. The deletion can be performed by $('div.postcontainer').remove (); $('div.thread > br:not(.clear)').remove (); which reduces the thread to the op. Clicking '[Update]' then demonstrates the effect.
Lord Nikon · 2019-03-15 14:46
Merely updating the page with a large number of replies does not seem to cause auto-reload.js >>12829 to insert replies in the wrong order. This can be tested by removing all replies but the first, due to >>12838 var leave1 = function () { $('div.postcontainer:gt(0)').remove (); $('div.thread > br:not(.clear):gt(0)').remove (); }; then checking that replies are in order after an update. var ordered = () => Array.from (document.querySelectorAll ('div.post.reply')).map (e => parseInt (e.id.substring (6))).reduce ((acc, val) => [acc [0] && (acc [1] < val), val], [true, 0]) [0]; It seems that a more complicated scenario is needed to account for out-of-order posts.
Chani · 2019-03-15 17:34
I wrote a basic raytracer in Julia for a cross-language benchmark. Performance in the REPL is excellent and comparable to C++ with g++ -O2 .
Tequila · 2019-03-15 17:35
>>12861 Rendering the image above took a couple of seconds on my old laptop.
overriding · 2019-03-17 04:09
Here is one mechanism that will cause auto-reload.js >>12829 to skip posts when updating. When polling the thread is reread via ajax and the replies are looped over and added if they pass this test: $(data).find('div.post.reply').each(function() { var id = $(this).attr('id'); if($('#' + id).length == 0) { This seems reasonable in isolation, since it avoids readding existing replies. The problem appears in js/post-hover.js which attempts to support hovering over crossboard links. https://github.com/lainchan/lainchan/blob/master/js/post-hover.js If a linked post is hovered and not already present in this thread, its thread is obtained via ajax and then: var mythreadid = $(data).find('div[id^="thread_"]').attr('id').replace("thread_", ""); if (mythreadid == threadid && parentboard == board) { $(data).find('div.post.reply').each(function() { if($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) { $('[data-board="' + board + '"]#thread_' + threadid + " .post.reply:first").before($(this).hide().addClass('hidden')); } }); } else if ($('[data-board="' + board + '"]#thread_'+mythreadid).length > 0) { $(data).find('div.post.reply').each(function() { if($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) { $('[data-board="' + board + '"]#thread_' + mythreadid + " .post.reply:first").before($(this).hide().addClass('hidden')); } }); } else { $(data).find('div[id^="thread_"]').hide().attr('data-cached', 'yes').prependTo('form[name="postcontrols"]'); } If the post belongs to this thread, or to a thread already stored in this one, it is added as a hidden post to the top of its thread in reverse order. If the post belongs to another thread not yet stored in this one, its entire div.thread is added as a hidden element to the top of the postcontrols form. This can be observed in the new CA thread >>12868 where someone linked the old one from the archive. Before hovering over the archive link the postcontrols form starts with the hidden input and div.thread#thread_9558. After hovering over the archive link the postcontrols form acquires a hidden div.thread#thread_17 as its first child. In this particular case this will not be a problem, because all post numbers in the old thread are lower than all post numbers in the new thread. The problem is that while post numbers are unique within a board, they are not unique across boards. By storing a foreign thread in the current one, post-hover.js risks duplicating post numbers and thus duplicating ids, which is already illegal in plain HTML. The id namespace of a page is flat, so care must be taken to separate ids that use the same post number. For example, templates/post_reply.html uses #pcNNN for post containers and reply_NNN for replies. https://github.com/lainchan/lainchan/blob/master/templates/post_reply.html The same care is not exercised by post-hover.js with crossboard post numbers, which can collide. This lack of namespacing of crossboard ids in a flat page id space was introduced by czaks on Aug 5 2013 in commit: https://github.com/lainchan/lainchan/commit/185e68de47210b9886d87196832d166ff85dc72c Auto-reload.js can skip posts like this. If the current thread has a crossboard link to a thread with higher ids, that thread is stored in the current one upon hover. If the current thread then receives a new reply with a post number that is already used in the foreign thread, that reply will not pass the insertion test and auto-reload.js will not add it, believing it to be already present. The solution is to either have post-hover.js use a different storage location for foreign threads, outside the DOM, or to apply namespacing to all ids inserted from foreign threads, using their board name. For example, the foreign thread's div.thread could be traversed and any id modified with the foreign board name as a prefix or suffix. The same scheme would then be used for looking up foreign posts. No offense to the original Tinyboard crew but the architecture of JS extensions is looking increasingly like a haphazardly thrown together pile of good intentions, held up by hope and faith.
Yu-ichi · 2019-03-17 09:45
this. to be honest, fam, smh, shygd, etc.
Marly Krushkhova · 2019-03-17 12:32
Experimental verification of >>12885. On the test board, a music post is linked that is in a thread that contains the next post number from the test thread. The next test post is the skip test. This procedure follows: - Uncheck auto reload. - Inspect the page and remove the skip test post's postcontainer and br. - Enabling auto reload brings in the removed post as if it were a new reply. - Uncheck auto reload again. - Remove the skip test post again. - Hover the music post's link and wait for the overlay to load. - Enabling auto reload does not bring in the removed post. Instead, the countdown interval is doubled. This happens because the removed post's id was added by post-hover.js as part of the hidden copy of the music thread. So auto-reload.js considers that reply to be already present and sees nothing that needs to be inserted. To verify this final state: >> $('#reply_725') Object { 0: <div#reply_725.post.reply>, length: 1, context: HTMLDocument → 528.html, selector: "#reply_725" } >> $('#reply_725').parent ().parent () Object { 0: <div#thread_667.thread>, length: 1, prevObject: Object, context: HTMLDocument → 528.html } >> $('#reply_725').parent ().parent () [0].attributes NamedNodeMap [ data-board="music", id="thread_667", class="thread", style="display: none;", data-cached="yes" ]
Hitomi · 2019-03-18 15:54
>>10399 Hello fellow lainons. I'm making a pipeline system in C, here it is: #include <stdio.h> #include <stdlib.h> /* * A single task in a pipeline: * process - function pointer to the task * next - next task to be run after this one */ typedef struct pipe_node { int (*process)(void *in, void **out); struct pipe_node *next; } pipe_node; /* * A pipeline describing the whole job to be done: * data_in - input data * data_out - output data, need to be freed after the run_pipeline was called * start - the first task to be run in the pipeline * end - pointer to the last task in the pipeline, only present to simplify * adding a new task */ typedef struct pipeline { void *data_in; void *data_out; pipe_node *start; pipe_node *end; } pipeline; /* * Function to demonstrate the pipeline. Writes "Hello, from Foo" in the out * buffer and returns 0. */ int foo(void *in, void **out) { printf("foo:%s\n", (char *)in); *out = malloc(16); sprintf(*out, "Hello, from Foo"); return 0; } /* * Function to demonstrate the pipeline. Writes "Hello, from Bar" in the out * buffer and returns 0. */ int bar(void *in, void **out) { printf("bar:%s\n", (char *)in); *out = malloc(16); sprintf(*out, "Hello, from Bar"); return 0; } /* * Runs the whole pipeline. The function will return 0 if successful and -1 or * the value from one of the task if there was a error. The data_in in the * pipeline will be freed if at least one task was in the pipeline, and * the out data should be in data_out parameter. */ int run_pipeline(pipeline *pipe) { int ret = 0; pipe_node *next_job = NULL; if (!pipe) return -1; next_job = pipe->start; while (next_job != NULL) { ret = next_job->process(pipe->data_in, &(pipe->data_out)); free(pipe->data_in); if (0 != ret) return ret; next_job = next_job->next; if (next_job) { // is this the last task? pipe->data_in = pipe->data_out; pipe->data_out = NULL; }// else: for the last task, leave the data in the out buffer } return 0; } /* * Allocates memory and adds the new task to the pipeline. Will return * value < 0 if failed. */ int add_task(pipeline *pipe, int (*task)(void *in, void **out)) { pipe_node *new = NULL; if (!pipe) return -1; new = malloc(sizeof(pipe_node)); if (!new) return -2; else { new->process = task; new->next = NULL; } if (NULL == pipe->start) pipe->start = new; // this is the first task in the pipeline else pipe->end->next = new; // chain with the last task pipe->end = new; // add the new task to the end of the list return 0; } /* * Clean up the memory. */ void close_pipe(pipeline *pipe) { pipe_node *node; if (!pipe) return; node = pipe->start; while (NULL != node) { pipe->start = pipe->start->next; free(node); node = pipe->start; } pipe->end = NULL; free(pipe->data_in); free(pipe->data_out); } int main() { char *data = malloc(12); sprintf(data, "Hello world"); pipeline P = {data, NULL, NULL, NULL}; add_task(&P, foo); add_task(&P, bar); add_task(&P, foo); run_pipeline(&P); printf("final: %s\n", (char *)P.data_out); close_pipe(&P); return 0; } What do you think? On the occasion this is a example of a program that is a valid C code but won't compile under C++ (there are at least 2 reasons why).
Y.T · 2019-03-18 17:00
>>12900 What is the purpose of such a program?
Eldon Tyrell · 2019-03-18 17:03
>>12900 reminds me of a unit test harness I built once upon a time. I'm working on a ring buffer at the moment. Having completed Binary & AVL Trees, Linked Lists, and low level page allocations, once the ring buffer is built I can implement a tokenizer and lexical parser for my lispish language. Goal is to create a platform / language that is designed to be bootstrappable from minimal featureset. So, a very RISCy platform may not have opcodes for multiplication (can do it with adds & shifts), or may restrict memory load results to one register. After implementing a very minimal base of operations (in hardware / FPGA or software VM) the system will be able to run operations which bring a compiler and development environment online. Then new opcodes & features can be added to the assembler / compiler and the platform rebuilt to take advantage of the features. The compiler would accept opcode to perform multiplication, but be able to emit code for a chipset lacking a multiplication operation. Similarly, stack-frame modification opcodes break down into simpler instructions requiring only add, load-reg-from-addr, and set-addr-from-reg opcodes. My desire is to have a pathway for beginners in new hardware design to utilize a more complete development environment without being subject to the Ken Thompson Hack. Imagine 'Structure and Interpretation of Computer Programs' but you make the hardware too. I've noticed that polish notation with a slight modification can result in C-like (Algo) syntax. Primarily I wish to not have any "order of operation" shenanigans, since even C's -wALL suggests putting needless parentheses around things because programmers can't remember the web of complex operation ordering rules. I hear objective C has explicit ordering of operation, but Ive never bought an Apple product, and Apple IIe BASIC in elementary school was the last time I coded for their platforms. In Lisp we have explicit order of operations and parens: (func0 param0 param1 func1( p0 p1 )) But we can do away with the parentheses if we know that a parameter is a function and how many parameters said function takes. func0 param0 param1 func1 p0 p1 This is similar to the more commonly implemented reverse polish notation, where parameters are pushed on the stack then operations performed, instead we push the operations / functions. Consider variable assignment: a = b; // C (= a b) // lispish = a b; // in my new lang. a = b; // also valid in my new lang. int a = (b + c) * d; // C ( = a' (* (+ b c) d); // Lispish = a' * + b c d; // my new lang a' = b + c * d; // also valid in my new lang, order of ops = L->R Parenthesis are still needed to nest a statement result within a statement. Meh, we'll see if the syntax holds up to the smoke test of developing a self hosting compiler...
queue · 2019-03-18 20:20
>>12901 You can look on this as a way to organize your code. It's usefull if you process some data and after that you send the data to a next function to process it further, and so on. Think about what a linux command "ls | grep test" would do. It would run the ls cmd, and then pass it output to grep cmd. Lets say you have 20 different "flows of a application". You could write C int flow_1() { int ret = 0; ret = foo_1(in_buf, out_buf); if (ret != 0) return ret; ... ret = foo_10(in_buf, out_buf); if (ret != 0) return ret; return 0; } and then write 19 more "flow" functions where in each "flow" function after calling a foo_ function you check the result of that function, or you do this: C int flow_1() { ... add_task(&P, foo_1); ... add_task(&P, foo_10); int ret = run_pipeline(&P); } Which is less code to write because you hide the error checking in the run_pipeline function. Also you could create the flow dynamically. Lets assume you are converting a RAW image file from a camera to a jpg format. The flow of this convertion could depend on the options that the user picked: take RAW file -> add sharpness -> add contrast -> add saturation -> convert to jpg Where like I said this would be dynamic and harder to implement in a different way. Here you would just add the correct functions to the pipeline and then just convert from RAW to jpg doing all the steps that the user picked (added using add_task function). >>12902 >I'm working on a ring buffer at the moment. Having completed Binary & AVL Trees, Linked Lists I guess that all those structures are similar in a way when you look on the implementation of them very closely (you have a some strucure with a pointer to a different strucure of a same kind, like in my case pipe_node that points to the next element of the pipeline). What changes are the algorithms to add and modify the strucure in a bigger sense (add a new element to a AVL tree, ok but you have to reevaluate the tree so it will be balanced, add a new element to a linked list in a middle, ok but you have to switch some pointers here and there). Does your AVL tree algorithm balances any given tree or re balances the tree only when you add a new element to it? I once (long time ago) implemented a AVL tree algorithm but it only re balaced the tree when adding a new element (meaning that I had to start always from a one element tree). If I rememeber correctly the balancing of any given tree is a different algo. then re balancing it after adding just one element.
sizeof · 2019-03-19 02:20
>>12903 Ah ok cool. Thanks for explaining. I never thought of something like that.
overriding · 2019-03-19 03:34
>>12903 I started with the specification of program structures features needed to build a linker & assembler, and then created the minimal set of opcodes required for hardware to implement. Presently, I have to make all these data structures out of only the small set of opcodes, but macros help. I'm essentially bootstrapping a compiler out of machine code on the platform itself -- as opposed to cross compiling from a separate host environment then loading the code. This should provide a "clean" pathway that eliminates any chance of the Ken Thompson (compiler) Hack sneaking in. Imagine your system is pwned by Megacorp. The compilers available will also inject malicious code into programs. The hex editors will lie and not display the malicious code. Building a new OS, or even a new chip-sets won't save you so long as you start with with Megacorp's tools they will compromise your new system and infect your new compiler (hypothetically... but seriously, folks who care about security have to think this way). Ken Thompson (original implementer of Unix) felt so strongly about this he gave a paper about this exploit vector rather than his ACM award acceptance speech for achievements (making Unix). Think about that. https://www.win.tue.nl/~aeb/linux/hh/thompson/trust.html http://archive.is/gV6BK Lain should find it an interesting / entertaining read. Since the complier touches everything else, and even reading the open source code won't reveal the Ken Thompson hack, the only way to avoid this type of Megacorp exploit is to bootstrap the system from scratch. Once upon a time PCs could boot from serial port so you didn't have to expose your hardware to another computer. But optimally we'd want at least the first gen of our new clean Megacorp-free hardware to be able to accept the initial boot sequence manually. That's basically what I'm doing, creating the base software you can enter manually to get hardware up and usable. The ring buffer takes in bytes for processing into tokens which get stored in a separate ring buffer. Not unlike your processing pipeline. For compilation I also need hooks to fork or bypass the pipeline, for example, emit comments, insert an include file, or ignore blocks of code for conditional compilation. C and many other languages are designed to be compiled in a single pass (to avoid rewinding the tape drives, a slow process to seek to the beginning of the drive). Since modern drives have no such seek penalty my approach is to emit multiple streams of intermediary representation (serialized abstract syntax trees), then perform additional passes until the code is able to be linked into an executable binary. Since abstract syntax trees (ASTs) can be interpreted (at compile time) rather than compilation into machine opcode, this approach has the benefit that the compiler can be very lean and modify itself at compile time by loading intermediary AST macros. This results in a compiler that is very small and thus easy to bootstrap, but which needs to process runtime AST before doing actual compilation. The AVL trees are used therein primarily for symbol table lookups (and to generalize command line options). You can actually nerf the AVL tree and just use a slow search over an unordered list (which is simple to code, but slow to compile). The 1st iteration bootstrap environment uses such slow but technically correct approaches to get things rolling. The AVL Tree and other stuff (hash tables, etc). Can then be entered, compiled, on the platform and replace the slower code. My implementation can efficiently merge two AVL trees, but it can't take just any ol binary tree and balance it. I do have a separate function to handle that: If the binary search tree can be iterated in order we can generate a balanced AVL tree in O(n) time (2n): Iterate the binary tree in order, adding its elements to a vector. O(n). The "middle" of the list will become the root node. The root node holds two separate indexes in the vector for right and left side. Iteratively create new nodes subdividing these index ranges until each node points to only one index for both its start and stop index. Each node is processed twice, once to add to the vector, once to split into left / right children. Using this method we can accept batches of sorted data, convert it to AVL trees then efficiently merge the trees together. If the batch is unsorted, might as well just add elements directly to the AVL tree to perform the sort and construction in one shot. Rather than rebuild the trees from sorted sets of names I store symbol space as a serialized AVL trees along with the associated AST. I.e., root node stored first, its left node, grandparent left, etc. until no more lefts, then walk back one node and read a right node, then all of its lefts, then walk back up until a right node needs to be read, etc. This has the effect of walking the tree as if an in-order traversal, and avoids use of recursion. (all of my AVL functions avoid recursion [stack overflow] using iterative methods) I had once toyed with the idea of making an OS out of nothing but data processing streams (rather than files as per *nix), but reliance on reliable delivery of stream data made it too brittle to scale up, and too expensive to track state of every stream at once. I'm still convinced there's something interesting to explore there, however.
if · 2019-03-20 11:32
The new post insertion in ajax.js is even more broken than in auto-reload.js >>12838. https://github.com/lainchan/lainchan/blob/master/js/ajax.js $(data).find('div.post.reply').each(function() { var id = $(this).attr('id'); if($('#' + id).length == 0) { $(this).insertAfter($('div.post:last').next()).after('<br class="clear">'); - The insertion needs the branching that handles OP-only threads. - The inserted element has to be the parent div.postcontainer instead of the div.post.reply. - The insertion point is explained in the linked post. - The 'after' should be the '<br/>' used by templates/post_reply.html. Since this is causing trouble and is used in at least two places, it might be worth factoring out into a function.
Koos van der Merwe · 2019-03-20 22:40
>>12903 >>12900 It's nicely done. Your C code is very clean. Does your pipeline process things other than null-terminated strings? As it is, there is no type encoded in your program with regards to the allocation that the processors (foo and bar) perform. malloc will properly free them as it knows the runtime size. Can you however think of a way to encode the size of memory allocations so that the various parts can at least assert at runtime that the conversion they are about to perform has properly assumed the type of the values involved? Can you also think of a way to retrieve the intermediate values in the pipeline? Another nice feature would be preemptive freeing of buffer memory, i.e. a process in the pipeline can inform the pipeline that it will not need access to the input memory anymore. Also, you could introduce a method of pausing execution of the pipeline.
The Oracle · 2019-03-21 09:14
>>12917 >It's nicely done. Your C code is very clean. Tkanks! >Does your pipeline process things other than null-terminated strings? It might. Thats way the void * as the data_in and data_out variables in the pipeline struct. As long as the foo, bar and other functions knows what are they getting then you could give them anything (a structure, a null-terminated string, a number). Inside the foo function I would just need to do the right cast and interpret the the data received in a correct manner. > Can you however think of a way to encode the size of memory allocations so that the various parts can at least assert at runtime that the conversion they are about to perform has properly assumed the type of the values involved? Look up flex-arrays in C: https://en.wikipedia.org/wiki/Flexible_array_member This would change the code posted above in such a way: C typedef struct flex_array { int size; char buf[]; } flex_array; /* * Function to demonstrate the pipeline. Writes "Hello, from Foo" in the out * buffer and returns 0. */ int foo(void *in, void **out) { printf("foo (%d): %s\n", ((flex_array *)in)->size, ((flex_array *)in)->buf); *out = malloc(sizeof(flex_array) + 16); ((flex_array *)*out)->size = 16; sprintf(((flex_array *)*out)->buf, "Hello, from Foo"); return 0; } /* * Function to demonstrate the pipeline. Writes "Hello, from Bar" in the out * buffer and returns 0. */ int bar(void *in, void **out) { printf("bar (%d): %s\n", ((flex_array *)in)->size, ((flex_array *)in)->buf); *out = malloc(sizeof(flex_array) + 16); ((flex_array *)*out)->size = 16; sprintf(((flex_array *)*out)->buf, "Hello, from Bar"); return 0; } int main() { flex_array *data = malloc(sizeof(flex_array) + 12); data->size = 12; sprintf(data->buf, "Hello world"); pipeline P = {data, NULL, NULL, NULL}; add_task(&P, foo); add_task(&P, bar); add_task(&P, foo); run_pipeline(&P); printf("final: %s\n", ((flex_array *)P.data_out)->buf); close_pipe(&P); return 0; } As you can see I didn't change the implementation of the pipeline, I only changed the foo, bar and main function to make it work. This also addresses your first question (can the pipeline process something else then null-terminated string). >Can you also think of a way to retrieve the intermediate values in the pipeline? The pipeline struct could have a additional structure inside (a stack, or some sort of list) that would keep all the intermediate values. Then in close_pipe function this stack would free the memory. >Also, you could introduce a method of pausing execution of the pipeline. Probably (i'm not sure it would work properly), the setjmp/longjmp could be used to exit and return to the run_pipeline function (pause the pipeline and unpouse it again). The next_job in the run_pipeline function could be passed as the value longjmp (and received by setjmp) so the run_pipeline would know where in the loop it poused execution. I feel however that I would have to have a real good reason to implement it that way as I think it would make the code less friendly to read and understand. This also was out off the scope when writen the code. If your interested in such a thing then have a look at how to implement coroutines in C using longjmp.
Koos van der Merwe · 2019-03-22 10:45
The url caching mechanism of post-hover.js >>12885 is too strict. var dont_fetch_again = []; [...] $post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id); if($post.length > 0) { start_hover($(this)); } else { var url = $link.attr('href').replace(/#.*$/, ''); if($.inArray(url, dont_fetch_again) != -1) { return; } dont_fetch_again.push(url); [...] An external thread is only acquired once. If the external thread gets a new reply after being cached, and then the current thread gets a new reply that links to the new reply of the external thread, this link will not show the post overlay on hover because the new reply of the external thread is not in the cached copy. Instead of a flat url list, the cache should be a map from urls to at least the time of last acquisition and the highest contained post number. Then, if the sought post number is higher and the interval since the last acquisition greater than a cooldown value, the external thread should be reread and its mapped values updated. This will also allow the current thread's hovers to reflect external post removals, which in the current version are only made visible by reloading the page.
renames · 2019-03-24 21:15
I'm working on a .vue file bundler since I think Webpack is unnecessarily complicated.
Anamika · 2019-03-26 01:51
>>11053 HtmlAgilityPack is the soykaf B^)
Cypher · 2019-03-26 13:35
I've been working on a text editor library coupled with a TUI text editor, both in C, for fun and to get more used to the language.
Tequila · 2019-03-26 15:41
>>13008 Your using ncurses, or did you pick something more exotic?
Unsigned · 2019-03-26 21:38
>>13009 I'm using ncurses, I feel a bit too unfamiliar with C to play around with libraries that don't have much resources available when inevitable issues arise. I do try to keep the screen drawing fairly centralised to a few base functions though, so with some luck it shouldn't be too hard to move to a different TUI library or even GUI if I feel brave later.
Yuki Nagato · 2019-03-28 08:36
>>13016 I wish you luck, but if your really think about changing the library in the future then you should encapsulate the ncurses function calls. Adding a layer between the app and the library would allow you to change the inner working of this midel layer function (read only in one place) what would be far less painfull then going throug all the code and changing all the ncurses function calls (think what would happen if the new lib. would have incompatibil (with ncurses) function calls, like different sequence of function to call or something). However if you won't change the ncurses lib to something else then adding a midle layer to encapsulate ncurses would be a waste of time in this case. I know you can't predict the future but it pays to think about those things in advance.
Nanashi No Gombe · 2019-03-29 00:02
Working on my command line "anki" in C
Church · 2019-03-29 00:51
In addition to a mechanism that causes auto-reload.js to skip >>12885 posts, here is one mechanism that causes posts to appear out of order. Clicking on '[Last 50 Posts]' on an index page loads a page like https://lainchan.org/%CE%BB/res/10399+50.html with the OP and the last 50 replies -- choosing a large thread. If one of the loaded posts is deleted between updates, usually one of the last ones, and no new posts are made in the same update interval, the next update will fetch a 50-post slice that has moved back by one position. The first post of the new slice has a post number smaller than the first displayed reply and is not in the current DOM, so auto-reload.js will consider it a new post, and just like any other new post it will be added to the end of the thread. This causes it to be out of order. To replicate this open a +50.html page, uncheck auto update, then inspect and remove the first reply's postcontainer and br. This is equivalent to having had the last reply of the incremented slice removed. Clicking '[Update]' then brings in a lower numbered post, into the last position. To deal with this in the general case, binary search can be used to find the insertion point that maintains the sorted list invariant at every step. To accelerate the most common case of a new reply, the higher end can be tested first. To avoid each inserter script having to reinvent the wheel, sorted post insertion that correctly handles OP-only threads should be moved into a common utility function.
sage · 2019-03-29 21:55
>>13035 I just made a repository out of it https://github.com/jennydoe/cards for those interested
Rick Deckard · 2019-03-31 01:04
>>12417 I'd love to see you finishing it.
H.R. Giger · 2019-03-31 23:39
Currently working on a runtime system for my language experiments. It's just past the phase of being able to run simple processes written directly in FASM but not anywhere beyond that. A process currently looks something like this ;; init ;; rcx:PID (from) ;; interface ;; rax:TAG (message tag) [in] ;; die: ;; rcx:PID (from) [in] ;; poll: ;; rcx:PID (from) [in] ;; rdx:INT (bytes if any) [out] ;; rax:ERR [out] ;; write: ;; rcx:PID (from) [in] ;; rdx:STRING (text) [in] ;; rdx:INT (bytes written) [out] ;; rax:ERR [out] ;; flush: ;; rdx:INT (bytes printed) [out] ;; rax:ERR [out] ;; unknown: ;; rax:ERR [out] ;; lightprocess Stdout, 0x04, 4096 ; <name>, <external pid>, <allocated space for ringbuffer> xor qword rdi, rdi mov rax, sys_epoll_create ; setup epoll (not finished) syscall mov [Stdin_process.stack], rax yield Stdout, rcx .loop: test rax, rax jz .die cmp rax, 1 je .poll cmp rax, 2 je .write cmp rax, 3 je .flush jmp .unknown .die: xor rdi, rdi mov rax, sys_close syscall mov rsi, rcx jmp near contextSwitch.loadRegisters .poll: .write: .flush: .unknown: mov rax, -1 return Stdout, rcx, .loop Processes at the moment don't do too much and the threaded interpreter along with it's primitives for the higher level code portion of this runtime has yet to be written. When they are, a compiler can finally be written in threaded code and eventualy promoted from FASM to the language this implements. Memory allocation and such is dealt with within the higher level language including GC for non persistent processes. It's not much but at least it's going somewhere. I would like to place static types on the higher level language but currently have little clue of how other than that it needs to be versioned as processes may change at runtime and cover session types which I've yet to implement properly outside of Idris.
Judge Fang · 2019-04-01 21:39
Making UTF-8 string handling functions in C. strlen, strncpy, etc. replacements but with UTF-8 validation. It's for a new cross-terminal textmode rendering engine, basically to replace ncurses because it can't handle the 24bit colors that are now available. ncurses uses FG / BG pairs as attributes. You call something like MakePair() or whatever. This is fine with 16 colors but 256 colors is pushing it 65536 color pairs (if we ignore "default" clear BG [shows your bg image in most terminals]). Extend that to 24bit colors and ncurses maintainer says it's not workable and no one needs that many colors... well, I guess lain is nobody. Even Win10 supports 24bit color and ANSI escape codes in the terminal now. However, it was like pulling teeth to get the ncurses maintainer to add a record to the termcap / terminfo databases to allow terminals to advertise they support 24bit color modes. He literally said he was reluctant to do so because he had PTSD from internet bullies who wanted ncurses. puuhleeeze. Aside: I'm sick and tired of "open sores" software - it's open source, but where some asshat has set up a fiefdom and made contribution or progress impossible. If I didn't know better I'd think they were a bunch of microsoftie spies trying to destroy our social software utopia. Pthreads maintainers are the same sort. The Long March through the institutions has succeed, but the movement was compromised long ago...
array · 2019-04-05 20:04
>>13035 I am adding csv support to my flash cards tool. Found a two years old C library to handle it. Now cards are loaded from a csv file and a stored back with some state. I have yet to push my changes.
Nguoi La · 2019-04-12 04:44
>>10399 I'm not familiar with Lua but why do you need to create a `Map` for `t` if you're only processing the value using your `f` function returning a List of tuple Also, I'm currently working on projects within my company relating to FinTech, I'm using Haskell and STM and doing Formal Proofs with Dicks
synchronized · 2019-04-12 12:44
>>13194 >I'm not familiar with Lua but why do you need to create a `Map` for `t` if you're only processing the value using your `f` function returning a List of tuple I'm not sure if I understand you correctly, but > There is no map function in Lua like in Python so I needed to implement it by my self > The map function returns a table(call it a list if you want) of function f results (not a list of tuple, unless you will call it a list of tuple of one element) > I needed a map function to pass it argument to the zip function (so it takes two tables as compines them). Not sure does this answer your question or not.
Zuse · 2019-04-12 12:57
i cant find any motivation to work on my university essays, seems like deadlines are going to *truly* motivate me
progn · 2019-04-14 02:29
Planning an app for workflow: calendar/todo/timetracking/personal project management kind of thing Plan to use Flutter so that if one day it is marketable then it can be ported to both mobile OS
Chani · 2019-04-14 04:14
Working on a small script to help interact with / manage my trello board at work.
John Titor · 2019-04-17 17:37
I just made a little script to download albums from Bandcamp in 128kbps. import sys import os import re import json import urllib.request class Album: track_nb = 0 tracks_url = [] tracks_title = [] title = "" artist = "" fp = urllib.request.urlopen(sys.argv[1]) url_bytes = fp.read() line_lst = url_bytes.decode("utf8").splitlines() fp.close() trackinfo = "" for l in line_lst: if re.search("^\s+artist\:", l): Album.artist = json.loads(l[12:-1]) if re.search("^\s+album_title\:", l): Album.title = json.loads(l[17:-1]) if re.search("^\s+trackinfo\:", l): trackinfo = json.loads(l[15:-1]) Album.track_nb = len(trackinfo) for t in trackinfo: Album.tracks_title.append(t['title']) Album.tracks_url.append(t['file']['mp3-128']) dirpath = "./" + Album.artist + " - " + Album.title + "/" try: os.mkdir(dirpath) except FileExistsError as e: raise for i in range(Album.track_nb): trk = urllib.request.urlopen(Album.tracks_url[i]) newfile = open(dirpath + str(i+1).zfill(2) + " - " + Album.tracks_title[i] + ".mp3", 'wb') newfile.write(trk.read()) trk.close() newfile.close() It needs some cleanup, and I have to find a way to add basic ID3 tags, ideally without using a pip package.
Kay · 2019-04-17 18:08
Boring and tedious gamedev scripting and configfile rewrites.
Jane Doe · 2019-04-17 20:55
>>13259 >It needs some cleanup - Use 'with' blocks for both 'open' and 'urlopen'. https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen https://docs.python.org/3/reference/compound_stmts.html#the-with-statement with open ("...", "...") as file: # process file - You do not need to catch FileExistsError if you reraise it immediately. - Using os.path.join is more robust than manually inserting slashes. https://docs.python.org/3/library/os.path.html#os.path.join - A plain colon does not need to be escaped in regexps. - Using either str.format or formatted string literals will streamline your 'newfile' name computation. https://docs.python.org/3/library/stdtypes.html#str.format https://docs.python.org/3/library/string.html#formatstrings https://docs.python.org/3/reference/lexical_analysis.html#f-strings "{:02d} - {}.mp3".format (i + 1, Album.tracks_title [i])
Lunch · 2019-04-18 00:00
>>13259 To avoid having to manually append at each step of the trackinfo loop, you can dump the loop in favor of: Album.tracks_title.extend (map (operator.itemgetter ("title"), trackinfo)) Album.tracks_url.extend (map (operator.itemgetter ("mp3-128"), map (operator.itemgetter ("file"), trackinfo))) https://docs.python.org/3/library/operator.html#operator.itemgetter And trackinfo should be initialized to the empty list.
Anonymous · 2019-04-18 12:37
>>13261 >>13262 Thank you very much for these suggestions. I love Python because I can make up a dirty but useful script in a short time by just looking at documentation on the fly, but I suck at writing idiomatic Python.
Lady Jessica · 2019-04-23 20:20
Messing with the lainchan thumbnailer. The APNG spec allows the first frame, the one with IDAT chunks, to be excluded from the loop by not prefixing it with a fcTL chunk. But a plain PNG thumbnailer will pick that unused first frame for the thumbnail. To assemble APNG chunks: class Fctl (Editor): def __init__ (self, width, height, x, y, delaynum, delayden, dispose, blend, file): self.width = width self.height = height self.x = x self.y = y self.delaynum = delaynum self.delayden = delayden self.dispose = dispose self.blend = blend self.file = file def edit (self, actions, context): bin = struct.pack ("> 4L 2H 2B", self.width, self.height, self.x, self.y, self.delaynum, self.delayden, self.dispose, self.blend) file = self.file if file is None: key = Action.KEY_TAG tag = b'IDAT' pos = next (filter ( lambda tup: tup [1] [key] == tag, enumerate (actions))) [0] else: pos = len (actions) - 1 actions.insert (pos, { Action.KEY_TYPE: Action.TYPE_FCTL, Action.KEY_TAG : b'fcTL', Action.KEY_DATA: bin, }) if file is not None: actions.insert (pos + 1, { Action.KEY_TYPE: Action.TYPE_FDAT, Action.KEY_TAG : b'fdAT', Action.KEY_FILE: file, }) return actions To output APNG chunks: class Executor (pc.Proxy): def handle_fctl_seq (self): tagcounts = self.processor.counter return tagcounts [b'fcTL'] + tagcounts [b'fdAT'] def handle_fctl (self, data): tag = data [Action.KEY_TAG ] bin = data [Action.KEY_DATA] seq = self.handle_fctl_seq () bin = struct.pack ("> L", seq) + bin self.emit (tag, bin) def handle_fdat_file (self, tag, seq, file): idats = pong.Read.onlyIDATs (pong.Read.chunks (file)) idx = pong.C.CI_LENGTH read = pong.Read.chunkData for idat in idats: leng = idat [idx] out = bytearray (4 + leng) out [:4] = struct.pack ("> L", seq) with memoryview (out) as mv, mv [4:] as mv4: read (file, idat, readinto = mv4) self.emit (tag, out) del mv4, mv, out seq += 1 def handle_fdat (self, data): tag = data [Action.KEY_TAG ] file = data [Action.KEY_FILE] seq = self.handle_fctl_seq () with open (file, "rb") as f: self.handle_fdat_file (tag, seq, f) https://wiki.mozilla.org/APNG_Specification
Jet Black · 2019-04-25 10:19
One feature of APNG over GIF is partial transparency, made possible by having a full alpha channel. To assemble the fan: def compute_data_clip (self, width, height, hypot): return ( PathList ([ RectanglePath (-hypot, -hypot, 2 * hypot, 2 * hypot), RectanglePath (0, -height, width, height)]), cairo.FILL_RULE_EVEN_ODD ) def compute_data (self, state): sub = state.sub hypot = sub.hypot w = sub.width h = sub.height steps = sub.count dx = dy = hypot clip = self.compute_data_clip (w, h, hypot) state.data = [ (k, steps, w, h, dx, dy, clip) for k in range (steps) ] def compute_instr (self, item, surface): k, steps, w, h, dx, dy, clip = item path, fr = clip alpha = ((k + 5) % steps + 1) / steps return TransformInstr.saver ([ Translate.from_dxdy (dx, dy), RotateDeg.from_deg (k * 360 / steps)], ClipInstr (path, TransformInstr ([ RotateDeg.from_deg (-360 / steps), Translate.from_dxdy (0, -h)], Paint.from_surf (surface, alpha = alpha)), fill_rule = fr))
Frank Garza · 2019-04-25 11:23
And I see that the code tags still lose the indentation of the first line.
protected · 2019-05-02 08:22
>>10399 Currently doing some research on quantum resistant blockchain. Mainly aiming at coming to a conclusion whether or not Monero is quantum secure or not. So far it appears that public addresses on Monero are merely a point on an elliptic curve, which appears to not be quantum resistant. While BTC's public address is a hash of the public key, thus being quantum resistant. Then there is of course the whole question of the ring signature. If I'm not mistaken than quantum computers should be able to reveal the signer of a transaction but only if they use 'double' ring signature. Any anons done some work on that topic?
Nobody special · 2019-05-02 09:49
Pretty much finished coding up a GNU getopt() replacement (unix-style command line option processor). Pic from debugging the state machine that runs it. It accepts Unicode (UTF-8) parameters and option names (which I call command line Choices), handles the standard options formats like -ABC=42 (A,B,C are each parameters, C takes an option), equivalent to -ABC42 -ABC 42, or -A -B -C 42, etc. Long name aliases can be defined --Alpha, --Beta, and automatically generates sorted help listings and detailed help for individual items. Has the standard - to mean STDIN/STDOUT or -- to discontinue option parsing. Parameters may be statically typed. Just have to work out an oversight in the way I parse multiple parameters to choices (should -C42 -C123 be same as -C 42 123, I have both "choice may repeat", and "choice takes a list of args" flags, but no way to distinguish the two internally (both invoke -C choice twice), except the -C42 -C123 would error if no "choice may repeat" flag. Maybe just merge the options into one, have "list" imply multiple appearances of option allowed. To smoke test the little lib I'm writing a simple command line tool to perform Base91 encoding / decoding. I actually just found out someone else independently created a Base91 encoding calling it "BasE91". My encoding grew out of Base96 ASCII encoding used for sliding window compression. IMO, my implementation is superior as it supports alternate characters, is string quotable and compatible with HTML / XML without needing escapes, and uses leftover char values to perform simple Run Length Encoding compression of input data (Adobe's ASCII85 (base86) compresses a short run of zero bytes to a single char, but I can compress a run of up to 77 octets into two Base91 digits. Base91 is useful because each pair of digits can store 13 bits of binary data. My Base91 encoding also supports copy / paste concatenation: you can just paste two runs of already encoded data together to concatenate them, no need to decode and re-encode. You can manually inject delimiters to use as escapes or for multiplexing the data streams, or to delineate multiple data fields. The decoder can stop at delimiters then resume, or ignore all delimiters to read all data as one contiguous data stream. The encoder can insert "using alternates" codes into the stream so that the decoder can automatically change to the proper input character set. It also has a very short (4 char) garaunteed multi-part mime separator of !!!! (this is guaranteed never to occur in my base91 encoded data, BasE91 has no such guaranteed separator). This was designed in because when doing multi-part messages over text exchanges (such as email) one typically has to guess a string that won't appear in the subsequent data in order to signal the termination of the chunk of data. I'm using this Base91 as an interchange format for a text based graphics project. I had thought, " I need a text based storage format for binary data... What would Base64 have looked like if it had been done more efficiently rather than accidentally slapped together?" [seriously, the Base64 charset is all out of whack, A-Z first? WTF? Contiugous in-order runs of ASCII would have allowed us to replace a slow look up table with a few much faster if / else statements]. So I set about making my One True Text Encoding - The Right Way(tm) [hoping I'd never have to make another one again]... then after I finished I found out someone published an RFC for a Base91 encoding (that's not compatible with HTML/XML unless escaped). Oh well, I'm still going to use my superior version. Now I'm trying to come up with a name for it (while documenting some misc source files (a RingBuffer is used to handle the IO buffers in my cmd line tool). I'm leaning towards SQAB91 - String Quotable ASCII Base91, as it's explicitly ASCII, plus I can have an ugly pigeon ch!ck as a "Squab" mascot. Apendix I: SQAB91 Character Table Hex | B91 | Chr Hex | B91 | Chr Hex | B91 | Chr Hex | B91 | Chr <span class="heading">===|=====|===== =====|=====|===== =====|=====|===== =====|=====|===</span> x23 | 0 | "#" x3D | 25 | "=" x5D | 56 | "]" x21 | 90 | "!" x24 | 1 | "$" x3E | 26 | ">" x5E | 57 | "^" x25 | 2 | "%" x3F | 27 | "?" x5F | 58 | "_" x26 | 3 | "&" x40 | 28 | "@" x60 | 59 | "`" x27 | 4 | "'" x41 | 29 | "A" x61 | 60 | "a" x28 | 5 | "(" x42 | 30 | "B" x62 | 61 | "b" x29 | 6 | ")" x43 | 31 | "C" x63 | 62 | "c" x2A | 7 | "*" x44 | 32 | "D" x64 | 63 | "d" x2B | 8 | "+" x45 | 33 | "E" x65 | 64 | "e" x2C | 9 | "," x46 | 34 | "F" x66 | 65 | "f" x2D | 10 | "-" x47 | 35 | "G" x67 | 66 | "g" x2E | 11 | "." x48 | 36 | "H" x68 | 67 | "h" x2F | 12 | "/" x49 | 37 | "I" x69 | 68 | "i" x30 | 13 | "0" x4A | 38 | "J" x6A | 69 | "j" x31 | 14 | "1" x4B | 39 | "K" x6B | 70 | "k" x32 | 15 | "2" x4C | 40 | "L" x6C | 71 | "l" x33 | 16 | "3" x4D | 41 | "M" x6D | 72 | "m" x34 | 17 | "4" x4E | 42 | "N" x6E | 73 | "n" x35 | 18 | "5" x4F | 43 | "O" x6F | 74 | "o" x36 | 19 | "6" x50 | 44 | "P" x70 | 75 | "p" x37 | 20 | "7" x51 | 45 | "Q" x71 | 76 | "q" x38 | 21 | "8" x52 | 46 | "R" x72 | 77 | "r" x39 | 22 | "9" x53 | 47 | "S" x73 | 78 | "s" x3A | 23 | ":" x54 | 48 | "T" x74 | 79 | "t" x3B | 24 | ";" x55 | 49 | "U" x75 | 80 | "u" x56 | 50 | "V" x76 | 81 | "v" Alternates x57 | 51 | "W" x77 | 82 | "w" Hex | B91 | Chr x58 | 52 | "X" x78 | 83 | "x" =====|=====|===== x59 | 53 | "Y" x79 | 84 | "y" x09 | 26 | "\t" x5A | 54 | "Z" x7A | 85 | "z" x20 | 3 | " " x5B | 55 | "[" x7B | 86 | "{" x22 | 26 | "\"" x7C | 87 | "|" x3C | 4 | "<" x7D | 88 | "}" x5C | 3 | "\\" x7E | 89 | "~" x7F | 4 | "", "\x7F", or "\u007F"
Yu-ichi · 2019-05-05 03:25
>>13460 Hmm. > span class="heading" ==<script>alert('hi');</script> Just checking...
Crash Override · 2019-05-05 03:56
>>13484 < and > seems to be escaped correctly still
dictionary · 2019-05-08 23:01
The fan sections in >>13376 have uniform transparency, so here is an example with gradient transparency. To paint an image with an alpha mask: class Mask (Instr): @ classmethod def from_surf (cls, surf, makemask): t = cls () t.surface = surf t.makemask = makemask return t def exec (self, exectx): ctx = exectx.ctx s = self.surface.get () w = s.get_width () h = s.get_height () ctx.push_group_with_content (cairo.CONTENT_ALPHA) mask = self.makemask.make (w, h) ctx.set_source (mask) ctx.paint () mask = ctx.pop_group () ctx.set_source_surface (s, 0, 0) ctx.mask (mask) def display (self): return "{} {} {}".format ( "mask", self.surface.display (), self.makemask.display ()) To make simple linear alpha gradients: class MakeMask: def make (self, width, height): pass def display (self): return self.__class__.__name__.partition ('_') [2] @ staticmethod def forname (name): cls = globals () ["MakeMask_" + name] return cls () class MakeMaskLinear (MakeMask): def points (self, width, height): pass def make (self, width, height): ps = self.points (width, height) lg = cairo.LinearGradient (* ps) lg.add_color_stop_rgba (0, 0, 0, 0, 0) lg.add_color_stop_rgba (1, 0, 0, 0, 1) return lg class MakeMask_west (MakeMaskLinear): def points (self, width, height): return (width, 0, 0, 0) class MakeMask_southeast (MakeMaskLinear): def points (self, width, height): return (0, 0, width, height)
John Doe · 2019-05-16 11:42
Moved the mask generation >>13506 from the mask consumer into the mask producer. This will later allow masks that are not generated by a single paint call. class Mask (Instr): def exec (self, exectx): ctx = exectx.ctx s = self.surface.get () w = s.get_width () h = s.get_height () ctx.push_group_with_content (cairo.CONTENT_ALPHA) self.makemask.make (ctx, w, h) mask = ctx.pop_group () ctx.set_source_surface (s, 0, 0) ctx.mask (mask) class MakeMask: def make (self, ctx, width, height): pass def display (self): return self.__class__.__name__.partition ('_') [2] class MakeMaskSource (MakeMask): def source (self, width, height): pass def make (self, ctx, width, height): src = self.source (width, height) ctx.set_source (src) ctx.paint () To make some radial alpha gradients: class MakeMaskRadial (MakeMaskSource): def radius (self, cx, cy): pass def stops (self, grad): grad.add_color_stop_rgba (0, 0, 0, 0, 1) grad.add_color_stop_rgba (1, 0, 0, 0, 0) def source (self, width, height): cx = width / 2 cy = height / 2 r = self.radius (cx, cy) rg = cairo.RadialGradient ( cx, cy, 0, cx, cy, r) self.stops (rg) return rg class MakeMask_radhypot (MakeMaskRadial): def radius (self, cx, cy): return math.hypot (cx, cy) class MakeMask_radmin (MakeMaskRadial): def radius (self, cx, cy): return min (cx, cy) class MakeMask_radmax (MakeMaskRadial): def radius (self, cx, cy): return max (cx, cy) As an example here is a Lain with radial fadeout composited over SICP. After three seconds it switches to the opposite pattern.
Leto Atreides I · 2019-05-16 21:02
https://github.com/Spar0w/batch-down/blob/master/batch-down.go I put this in the last one but no one responded so maybe I'll get some pointers now. This is something I wrote a while ago to download images in batch from websites. I couldn't get it to work on lainchan though as I based my regexp off of 4chan. If anyone has anhy pointers that would be cool.
Chan Siu Ming · 2019-05-17 19:03
>>11504 >>11505 The bookshelf idea could be really usefulif it helps students find the book they're looking for.
藤原純一 · 2019-05-18 06:15
Battleships in C with Ncurses I'm terrible at it C // end game elegantly void end() { getch(); endwin(); exit(STATUS_OK); } void main() { init(); /* Draw Game Boards */ // board positions int p1_board_y, p2_board_y, p1_board_x, p2_board_x; p1_board_y = p2_board_y = 2; p1_board_x = 6; p2_board_x = p1_board_x + 15; // boards WINDOW* p1_board = newwin(BOARD_SIDE, BOARD_SIDE, p1_board_y, p1_board_x); WINDOW* p2_board = newwin(BOARD_SIDE, BOARD_SIDE, p2_board_y, p2_board_x); // apply markers around player 1 board mvwprintw(stdscr, p1_board_y-1, p1_board_x, "1 3 5 7 9"); // top numbering mvwprintw(stdscr, p1_board_y+BOARD_SIDE, p1_board_x, " 2 4 6 8 10"); // bottom numbering for (int y = p1_board_y; y < p1_board_y+BOARD_SIDE; y++) { //side numbering mvwaddch(stdscr, y, p1_board_x-1, toChar(y-p1_board_y)); } // apply markers around player 2 board mvwprintw(stdscr, p2_board_y-1, p2_board_x, "1 3 5 7 9"); // top numbering mvwprintw(stdscr, p2_board_y+BOARD_SIDE, p2_board_x, " 2 4 6 8 10"); // bottom numbering for (int y = p2_board_y; y < p2_board_y+BOARD_SIDE; y++) {//side numbering mvwaddch(stdscr, y, p2_board_x-1, toChar(y-p2_board_y)); } // draw blank player map wbkgd(p1_board, COLOR_PAIR(WATER_PAIR)); wbkgd(p2_board, COLOR_PAIR(WATER_PAIR)); wrefresh(stdscr); wrefresh(p1_board); wrefresh(p2_board); wattron(p1_board, COLOR_PAIR(SHIP_PAIR)); draw(p1_board, 3, 1, P1_Submarine.size, SHIP, TRUE); wattroff(p1_board, COLOR_PAIR(SHIP_PAIR)); wrefresh(p1_board); wattron(p2_board, COLOR_PAIR(HIT_PAIR)); // why doesn/t this one work now? draw(p2_board, 4, 2, P2_Destroyer.size, HIT, TRUE); wattroff(p2_board, COLOR_PAIR(HIT_PAIR)); wrefresh(p2_board); getch(); werase(p1_board); werase(p2_board); wrefresh(p1_board); wrefresh(p2_board); end(); }
Chani · 2019-05-18 06:51
>>10399 >What are you working on? My website. Unironically going for something just a little above http://bettermotherfuckingwebsite.com/ in terms of design and minimalism. Fanciest thing it'll have will probably these pop-up notes I shamelessly copied from https://what-if.xkcd.com/ (I never figured out how to into webdev, especially CSS, myself): html <style> .ref { position: relative; } .ref-content { background-color: white; border: 1px solid black; bottom: 0px; display: none; font-size: 14px; left: 1em; min-width: 12em; position: absolute; } </style> Here's a sentence with a pop-up ref <span class='ref'> <sup> <a href='#' onclick='toggle(1)'>1</a> </sup> <span class='ref-content' id='ref-1' onclick='toggle(1)'> This is the pop-up ref! </span> </span> . Wow, wasn't that cool? <script> function toggle(n) { ref = document.getElementById(`ref-${n}`) if (ref.style.display === 'none' || !ref.style.display) { ref.style.display = 'block' } else { ref.style.display = 'none' } } </script>
Church · 2019-05-18 14:45
>>13603 > Fanciest thing it'll have will probably these pop-up notes i love it. i had to visit xkcd to make sure i knew what you meant, but yeah. it's really neat, i was thinking about doing the same for my personal wiki
renames · 2019-05-18 15:07
>>13593 finally getting that google maps for libraries/universities where it points an arrow at the book i am looking for?
Trinity · 2019-05-18 17:58
>>13609 I'm imagining a bunch of AR arrows layed on the ground, wall, cieling, etc to help you find the book in a fun and engaging way.
Random · 2019-05-18 18:04
>>13611 well, i for one would rather spend an hour playing an AR game in uni library to find my book than spending an hour in library looking for a book that isn't even there
Wintermute · 2019-05-18 23:03
>>13460 Ttransmuting the SQAB91 encoding protocol into a container format for bits. Unfortunately thanks to browsers, text encodings are sometimes required to handle binary data, cookies, local storage, etc. The stream delimiters are working nicely, however the look-ahead is a little too complex, I would like at most 2 bytes look ahead for decoding. The current exception made for a delimiter following a write of zero-bits is making the decoder code too complex, by doing 4 byte lookahead but only sometimes. I can greatly simplify the bit-precice delimiter handling code. Unfortunately, if I change the encoding I'll have to modify over 500 unit tests. Oh well, at least I wont ever have to design a text encoding again after this. Bit-level precision means you can write just 1 bit, 9 bits, 32, bits etc., i.e., vary the number of bits you write. And as long as you read back the same number of bits in the same order, you'll get back the same data. Writing 16bits is not guaranteed to be the same as writing 8 bits twice because the end platform may have differing endian. However, all writes are 8 bits then it's up to the reader to put longer words back together. I aim to reduce the number of function calls to put & get bits while also (optionally) solve the endian problem up to 32 bit words. So long as you read the same number of bits that you wrote at in the same place of the stream, your word's endian will be automatically converted into the host byte order. Variable-bit-length input is primarily for containing Huffman encoding or Algorithmic Encoding of data. But can also be used simply to transmit something like source code or .TXT files which you know only use 7bit ASCII. Imagine you're writing data using an Adaptive Huffman tree. It outputs data as 1 to N bits. This is fine for Base64, or ASCII85, (or that other guy's BasE91) until you get to the end of the stream. When you do, you'll have to emit a Huffman code that means stop. Otherwise the implicit 8 bit segmenting of data will leave you wondering how many significant digits are in that last octet. Base64 padding only lets you know how many octets were in the final character triplet. There are various ways of solving this issue. One is a Meta format such as encoding chunks of data then prepending a bit length before sending it. All such methods are lame because the containing transmission format could have just done this for you if it had bit-level precision reads. In the case of wire protocols, this can be forgiven, but not in the case of Base64, etc. encodings where you're twiddling the bits to pack the data stream to a different encoding anyway. For example: Adding an explicit stop code to a Huffman Tree reduces the performance of the entire tree slightly, i.e., it's not a fixed cost for that end stream token, but SQAB91 delimiters add only a single fixed length cost at the site of the delimiter. Runs of data are thus delimited with a code that says how many significant bits are in the final SQAB91 encoded pair of that sequence. This allows chunks of data to be sent, like a proper packetized format. One can use delimiters to multiplex the data stream and send frames of audio / graphic / input / audio / graphic / input, etc. I might as well also include a "synchronize" code, which would also allow rows & columns of data to be marked. Let's say the data has multidimensionality. You could just arrange for the first data before a delimiter to contain the number of subsequent columns in a row of data. However, if the data stream gets garbled you need some surefire way to "reset" and start again (or you may be displaying audio as graphics, etc.) It's trivial for any good bitstream container format to do this for you. So, I've backed off using !!!! as a guaranteed MIME separator. Now a !! pair is a "stop" delimiter that can be detected apart from ordinary delimiters - (or all delimiters can be ignored to simply concatenate data). These delimiters come at no extra cost if bit precision is desired because a pair of base 91 digits can represent 8281 numbers (0 to 8280), which covers 13 bits of binary data [0..8191] with 89 values to spare. This also solves an issue where one could concatenate data that uses differing sets of alternate characters. Encountering !! resets the stream, so if the data is to be concatenated !! can be appended (even after the fact) and then new inline alternate character set codes can be read again. This leaves me without a higher order separator, such a channel level or file level for the MIME separator. I suppose one could just guess and check (or not check and hope a random string of hex / GUID, doesn't magically appear as encoded text - the odds are astronomical of that happening by accident, but crackers rely on such "accidents" of coincidence to break stuff. Ah. I think I've got it. The SQAB91 encoder has alternates that are mutually exclusive. For instance reverse solidus ( "\" backslash) can not simultaneously be used with " " space or "&" ampersand. The decoder will not complain if you violate this rule, but the encoding charset can only have one value for #3, or for #4, etc. All the base 91 data is emitted in pairs. That means a pair of digits will not contain both a backslash and an ampersand. However, at the end of a stream / file, one could find /& or &/ if a stream is appended with differing alternate glyphs. A series of at least 4 alternating alternates for the same character could be used as a garaunteed MIME or "meta" separator above the scope of the SQAB91 encoding, such as: /&/& or &/&/ or '<'< or <'<' or ">"> or >">" ^any of those 4 char strings should be sufficient to preclude a (literal) edge case where the possibility of the string may occur. This is because the smallest SQAB91 output unit is 2 chars, and mutually exclusive alternates will not be emitted in the same pair of base 91 digits. Technically, only 3 of such alternating chars is needed to guarantee that the string will not occur in conforming SQAB91 data. However, if the reader does encounter such "impossible to emit" codes it will not complain. (Following the Internet design principle: Be strict in what you send, and forgiving in what you accept). That should tie up the last loose end of the bitstream container format without sacrificing any of the core features I desired. Forgive this rambling post, I use a text file or comment form to talk-out designs / rationales. Like Rubber Duck Debugging, but for design. https://en.wikipedia.org/wiki/Rubber_duck_debugging I'm just trying to not have to recode all these damn unit tests a second time. Not really worth saving anywhere, like a blog or anything, but perhaps worthy of a bump. image unrelated, sandboxes need not apply.
Nanashi No Gombe · 2019-05-22 02:30
>>13581 Use Lainchan's JSON API. See how the thread is represented as an array of objects representing posts and pay special attention to the "tim", "ext", and "extra_files" keys. To get you started, here's the JSON for this thread: https://www.lainchan.org/%CE%BB/res/10399.json
Mitnick · 2019-05-23 19:42
I wrote the Memory game (which we call "Pexeso" in my country) in JavaScript. It's pretty buggy tho. <!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Pexeso</title> </head> <body> <style> body { color: #444; background-color: #EEEEEE; font-family: sans-serif; padding: 50px; font-size: 20px; } table { table-layout: fixed; } td { text-align: center; } .pex { background-color: #AAAAFF; width: 100%; height: 100%; background-size: cover; margin: 0px; padding: 0px; border-style: solid; border-width: 2px; } .dex { width: 100%; height: 100%; background-size: cover; margin: 0px; padding: 0px; border-style: solid; border-width: 2px; } </style> <div id="opt"> Set the number of cards: <input type="text" id="a" size="3" oninput="changeb()"> * <input type="text" id="b" size="3">   <input type="submit" value="OK" onclick="start()"> <div id="cont"></div> </div> <script> function nic() { return 0; } function clicked(id) { idd = "di" + id; var selected = document.getElementById("sel").value; if (selected == 0) { document.getElementById(idd).setAttribute("style", "background-color: transparent;"); document.getElementById("sel").value = "1"; document.getElementById("whi").value = id; } else { document.getElementById(idd).setAttribute("style", "background-color: transparent;"); var prev = document.getElementById("whi").value; if (prev == id) { return 0; } else { prev = document.getElementById(prev).className; var now = document.getElementById(id); now = now.className; if(now == prev) { var score = document.getElementById("score").value; score = parseInt(score); score = score + 1; var pocett = document.getElementById("pocet").value; if(score == pocett) { alert("You won."); } document.getElementById("score").value = score; var prevv = document.getElementById("whi").value; prevv = document.getElementById(prevv); prevv.setAttribute("onclick", "nic()"); var noww = document.getElementById(id); noww.setAttribute("onclick", "nic()"); document.getElementById("whi").value = "0"; document.getElementById("sel").value = "0"; } else { var prevv = document.getElementById("whi").value; prevv = document.getElementById(prevv); prevv.setAttribute("onclick", "nic()"); var noww = document.getElementById(id); noww.setAttribute("onclick", "nic()"); var prevv = document.getElementById("whi").value; var noww = document.getElementById(idd); document.getElementById("whi").value = "0"; document.getElementById("sel").value = "0"; setTimeout(function(){ prevvv = prevv; prevv = "di" + prevv; prevv = document.getElementById(prevv); prevv.setAttribute("style", "background-color: #AAAAFF;"); noww.setAttribute("style", "background-color: #AAAAFF;"); var iddd = prevvv; iddd = "clicked(" + iddd + ")"; prevvv = document.getElementById(prevvv); prevv.setAttribute("onclick", iddd); var nowww = document.getElementById(id); var iddd = prevvv; iddd = "clicked(" + id + ")"; nowww.setAttribute("onclick", iddd); }, 1000); } } } } function changeb() { document.getElementById("b").value = document.getElementById("a").value; } function prirad(name, pocet) { var pex = Math.floor((Math.random() * pocet) + 1); var prvni = document.getElementById(pex); if (prvni.className == "pex") { prvni.className = name; } else { prirad(name, pocet); } } function priradd(name, pocet) { var pex = Math.floor((Math.random() * pocet) + 1); var druhy = document.getElementById(pex); if (druhy.className == "pex") { druhy.className = name; } else { priradd(name, pocet); } } function pair(pocet) { var set = 1; document.body.innerHTML = '<style id="barvy"></style>' + document.body.innerHTML; var pocett = (pocet / 2) + 1; while(set < pocett) { var cr = Math.floor(Math.random() * 255); var cg = Math.floor(Math.random() * 255); var cbl = Math.floor(Math.random() * 255); var name = 'px' + cr + cg + cbl; var ca = 'rgb('; var cb = cr + ', '; var cc = cg + ', '; var cd = cbl + ')'; var color = ca + cb + cc + cd; var barvy = document.getElementById("barvy") barvy.innerHTML = barvy.innerHTML + "\n" + ' .' + name + '{ background-color: '+ color + '; margin: 0px; padding: 0px; border-style: solid; border-width: 1px; } '; prirad(name, pocet); priradd(name, pocet); set++; } } function create(num) { function tr(i, w, h) { var tra = '<tr id="r'; var trb= '" width="'; var trc = '" height="'; var trd = '"></tr>'; return tra + i + trb + w + trc + h + trd; } function td(i, w, h) { var tra = '<td id="'; var trb= '" onclick="clicked('; var trc = ')" width="'; var trd = '" height="'; var tre = '" class="pex"><div id="di'; var trf = '" class="dex" style=" background-color: #AAAAFF; "> </div></td>'; return tra + i + trb + i + trc + w + trd + h + tre + i + trf; } var tab = document.getElementById("cont"); var n = 1; while (n < num) { tab.innerHTML = tab.innerHTML + tr(n, 600, 100) + '<tr height="10"><td> </td></tr>'; n++; } n = 1; var nn = 1; var tr = ""; while(n < num) { var x = "r" + n; tr = document.getElementById(x); var nnn = 1; while(nnn < num) { tr.innerHTML = tr.innerHTML + td(nn, 100, 100) + '<td width="10"></dr>'; nnn++; nn++; } n++; } } function start() { var pocet = document.getElementById("a").value; pocet = parseInt(pocet); if((pocet * pocet)%2 != 0) { document.getElementById("cont").innerHTML = "The number must not be odd!"; } else { document.getElementById("opt").outerHTML = '<table id="cont" border="0"></table><input type="hidden" id="sel" value="0"><input type="hidden" id="whi" value="0"><input type="hidden" id="score" value="0"><input type="hidden" id="pocet" value="0">'; document.getElementById("pocet").value = (pocet * pocet) / 2; create((pocet + 1)); pair(pocet * pocet); } } </script> </body></html>
John Doe · 2019-05-24 15:39
>>13704 Good job.
Rick Deckard · 2019-05-24 20:10
>>13704 Fun little game. I spent a few minutes playing it and I enjoyed it. I have two sugestions however. 1. Add some kind of score (like wen you win the game it would tell you how many moves did you make). 2. It would be easier (at least for me) if you would match some symols or numbers as the colors sometimes can be quite similar (played a board 6x6).
Moore · 2019-05-26 00:39
#!/bin/bash print_jails(){ printf "Running X11 Jails:\n$RES\n" let len=${#ops[@]}-1 for each in `seq 0 $len` do echo $each ${ops[$each]} done } do_work(){ if [ $grab == 1 ] then xclip -display $dis -selection CLIPBOARD -o | xclip -display :0 -selection CLIPBOARD -i else xclip -display :0 -selection CLIPBOARD -o | xclip -display $dis -selection CLIPBOARD -i fi } IFS=$' ' RES=`firemon --x11` declare -a ops=( `echo $RES| grep -o :[0-9][0-9][0-9]| awk '{ print $1 }'` ) unset IFS if [[ -z $1 ]]; then print_jails printf "\nEnter a display: " read choice printf "\nGrab paste(g) or pass paste(e): " read choice2 if [ $choice2 == 'g' ] then grab=1 else grab=1 fi dis=${ops[$choice]} do_work else case $1 in -l|--list) print_jails ;; -g|--grab) grab=1 dis=${ops[$2]} do_work ;; -s|--send) grab=0 dis=${ops[$2]} do_work ;; esac fi I run some applications inside some x11-firejail environments, makes it simple to pass paste between clipboards with out, i know theres a daemon for this, but i figure sometimes you dont want the paste passed.
Hagbard Celine · 2019-05-26 01:00
>>13742 oh wait... error in there, else statement second grab should =1
Ender · 2019-05-26 01:01
>>13743 0 oh god whats wrong with me
Batou · 2019-05-28 22:44
As an example of a mask >>13579 that is not a pycairo built-in, here is a grid of points: @ staticmethod def work_basegrid (size, steps): cell = size // steps rang = range (steps + 1) divs = [k * cell for k in rang] data = [[(x, y) for x in divs] for y in divs] return data This can be organized as a stream of quads in O(1) space: @ staticmethod def work_quads (data): flatten = itertools.chain.from_iterable starmap = itertools.starmap pairs = ither.pairs return flatten (starmap ( lambda row1, row2: starmap ( lambda pair1, pair2: (pair1 [0], pair1 [1], pair2 [1], pair2 [0]), pairs (zip (row1, row2))), pairs (data))) To paint a stream of quads with a stream of colors: class FreeOverGlass (FreeOver): @ staticmethod def scale (ctx, width, height, size): dim = size # + 1 sx = width / dim sy = height / dim ctx.scale (sx, sy) @ staticmethod def work_out (ctx, width, height, makecolors, *, steps = 16, delta = 12): size = 512 cls = dtes.TestMesh4 data = cls.work_basegrid (size, steps) if delta is not None: fun = cls.work_fun_delta (delta) cls.work_perturb (data, fun, 0) quads = cls.work_quads (data) color = makecolors (steps) FreeOverGlass.scale (ctx, width, height, size) polyline = kgeo.Path.polyline for quad, c in zip (quads, color): polyline (ctx, quad, True) ctx.set_source_rgba (* c) ctx.fill () To generate a stream of two colors in a chessboard pattern in O(1) space: @ staticmethod def chess_colors (steps, c1, c2): it = itertools return it.chain.from_iterable (map ( lambda x: x (), it.cycle (( lambda: it.islice ( it.cycle ((c1, c2)), steps), lambda: it.islice ( it.cycle ((c2, c1)), steps))))) A mask of transparent and opaque tiles in a chessboard pattern: class MakeMask_chess (MakeMask): def make (self, ctx, width, height): c1 = (0, 0, 0, 0) c2 = (0, 0, 0, 1) SaveRestore.via_matrix (ctx, lambda: pfre.FreeOverGlass.work_out (ctx, width, height, lambda steps: pfre.FreeOverGlassColors.chess_colors (steps, c1, c2), steps = 8, delta = None)) And assorted generic helpers: def pairs (stream): it = iter (stream) p = next (it) for q in it: yield (p, q) p = q class Path: @ staticmethod def polyline (ctx, points, closeit): it = iter (points) p = next (it) ctx.move_to (* p) for p in it: ctx.line_to (* p) if closeit: ctx.close_path () class SaveRestore (WrapInstr): @ staticmethod def via_matrix (ctx, dothis): matrix = ctx.get_matrix () dothis () ctx.set_matrix (matrix) Here is a Lain composited over SICP with a chessboard mask. After three seconds it switches to the opposite pattern.
Hacker · 2019-05-31 20:33
Massive arch install script, gonna add to it and make it more error friendly later but this is it atm, makes encrypted boot install automatically, adding other auto disk partitioning features... liking bash a lot lately was too big to post source here sorry https://raw.githubusercontent.com/quietok/HR-Tools/master/stupid-arch-scripts/HR-archinstall -files that go with it https://github.com/quietok/HR-Tools/raw/master/stupid-arch-scripts.tar.gz gz for easy download
Unnamed · 2019-06-01 06:31
I started getting into shellscript lately, made a few things for i3blocks
synchronized · 2019-06-01 22:59
I've started working on a shitty personal Neocities website recently. I'm a complete n00b at html (and coding in general), but it's been fun nonetheless. I spent several hours last night trying to figure out how borders work, and I'm ashamed to say that it took me a solid hour to figure out how to center text inside of a border. We all gotta start somewhere though, right? :P
pop · 2019-06-02 11:35
I don't trust lookup tables or branching statements. This code converts "someByte" into a pair of ASCII hex characters ['0'..'f'] without using branching statements (if / ?) or lookup tables. uint8_t ch = someByte; uint8_t cl = ch & 0xFU; ch = ch >> 4; // Tree Magic can walk multiple branches of The Path at once. *hexChar++ = 87u - (uint8_t)( ((int8_t)(ch - 10u) >> 7) & 39u ) + ch; *hexChar++ = 87u - (uint8_t)( ((int8_t)(cl - 10u) >> 7) & 39u ) + cl; This code reverses the above process, converting hex chars into binary again. uint8_t hi = *hexChar++; uint8_t lo = *hexChar++; hi |= 32u; lo |= 32u; hi -= 87u - (uint8_t)( ((sint8_t)(hi - 58u) >> 7) & 39u ); lo -= 87u - (uint8_t)( ((sint8_t)(lo - 58u) >> 7) & 39u ); *binary++ = ( hi << 4 ) | lo; It's just a small simple test of The Principle demonstrating that it is possible to replace the branches of conditional blocks with a single linear series of operations. This may improve pipelining and doesn't invoke the branch predictor or speculative code execution, and thus is immune to the Spectre and Meltdown family of exploits that Intel & AMD are scurrying around (unsuccessfully) trying to patch since it allows an attacker to read main system memory using branch predictor poisoning and/or cache-line access poisoning indirection (such as found in lookup tables). TL;DR, writing the only secure code on this planet.
Miho Iwakura · 2019-06-02 15:56
>>13807 No shame in that. Keep it up and have fun with it.
Pulse · 2019-06-03 07:00
>>13460 now working on porting said SQAB91 C code to Javascript. I had been using Emscripten at first to compile from C into ASM.js / WASM, but this time I just couldn't bear the ugly & bloated output it gives. I can write the ASM.js much better, cleaner, & faster by hand. For example, In place of ringbuffer.c's efficient replacement of tight loops with one or two memset() or memcpy() calls, RingBuffer.js uses TypedArray (JS access to low level data types), and can emulate memset() & memcpy() using TypedArray.fill(), TypedArray.set() and TypedArray.subarray(). Emscripten didn't do The Right Thing® and use these imports from ASM.js (nor WASM) which themselves call memcopy() or memset() internally (after the JS engine does its range check[s]). There's no need for a stdlib's malloc() implementation to exist in my code, nor much of the C standard library functions that Emscripten blindly crammed into the generated code -- And that transpiler doesn't understand VirtualAlloc() or memmap() [win / nix] OS allocation API I need for large page aligned allocations (which I'll use in later projects anyway). So I'd have to be implementing my own logic to do malloc()y things regardless. As much as I liked the dream of one C source being "compiled for the web" and as a command line application, the reality of generated code was like licking dead whales being mandatory for visiting the beach. I think I'll just drop the transpiler alltogether and search for a better way forward in future. As of now, that means manual reimplementation. I have a series of projects planned that each build on each other, so these early ripples of decisions may have far reaching impacts. It's a shame to drop Emscripten, but I think it's not a good fit for my lower level demands going forward. Once I had an ordinary Javascript SQAB91 implementation written. It benchmarked almost as fast as a hand rolled ASM.js / WASM implementation, those targets may become necessary later (as I reach for parity with the other site). I may just make the JS version a "reference implementation", since its "open source" by virtue of the platform. I'm under no delusion that my textual bitstream encoding protocol or other code will be widely used, and maintaining yet another FLOSS project is a PITA that's not worth the time investment, yet. I'll just focus on releasing .JS & some free win / Linux binaries for now. I've still got a few optimizations to finish up in the C source then port to the .JS code, but I should then be able to make an on-line GUI frontend for the simple lib... and move on to another project which makes use of the tools internally.
nibble · 2019-06-04 04:33
>>13817 Because people have gotten so far removed from the machine code and assembler, I frequently encounter programmers that think a compilers can magically beat a human proficient at assembly language. I'm optimizing a tight loop that the SQAB91 decoder spends a lot of time in, so let's beat the crap out of GCC's -O3, just for the hell of it. First thing's first, we can't blame GCC for not understanding the nuances of the character table above (Apendix I: SQAB91 Character Table). >>13460 // Ordinary and slow Lookup table method. if ( b91 == 3 ) {if ( flags & CL_SQAB91_USE_SPACE ) b91 = 91; else if ( flags & CL_SQAB91_USE_BACKSLASH ) b91 = 92; }else if ( b91 == 4 ) {if ( flags & CL_SQAB91_USE_LESSTHAN ) b91 = 93; else if ( flags & CL_SQAB91_USE_DELETE ) b91 = 94; }else if ( b91 == 26 ) {if ( flags & CL_SQAB91_USE_TAB ) b91 = 95; else if ( flags & CL_SQAB91_USE_DOUBLEQUOTE ) b91 = 96; } ascii = (cl_uint8)CL_SQAB91ToASCII[ b91 ]; // <- Will generate cache misses. Actually, a really amazing compiler COULD see the constant data table has long runs of sequential indexes (by design)... but no compiler is really all that amazing today. The problem is that last line there. Every time you have to fetch memory you could be waiting 100 to 1000 cycles or more depending on how bad the cache miss is. We're going to hand optimize out that LUT (lookup table) and effectively tell GCC all about it. ascii = b91; if ( b91 <= 24 ) ascii += 35; if ( b91 > 24 && b91 <= 55 ) ascii += 36; if ( b91 > 55 && b91 <= 89 ) ascii += 37; if ( b91 == 90 ) ascii = 33; if ( b91 == 3 && (flags & CL_SQAB91_USE_SPACE) ) ascii = 0x20; if ( b91 == 3 && (flags & CL_SQAB91_USE_BACKSLASH) ) ascii = 0x5C; if ( b91 == 4 && (flags & CL_SQAB91_USE_LESSTHAN) ) ascii = 0x3C; if ( b91 == 4 && (flags & CL_SQAB91_USE_DELETE) ) ascii = 0x7F; if ( b91 == 26 && (flags & CL_SQAB91_USE_TAB) ) ascii = 0x09; if ( b91 == 26 && (flags & CL_SQAB91_USE_DOUBLEQUOTE) ) ascii = 0x22; The top half applies the math derived from the table's sequential ranges. Bottom half applies the alternate glyphs to use if enabled by a flags field. The GCC -O3 optimizations emit this x84_64 ASM listing: 0xc0c8 mov %ebp,%r14d 0xc0cb mov %ebp,%r12d 0xc193 mov %ebp,%eax 0xc195 and $0x8000000,%eax 0xc19a mov %eax,0xc(%rsp) 0xc19e jmp 0xc203 <CL_Test_SQAB91+339> 0xc1a0 test %r15b,%r15b 0xc1a3 je 0xc249 <CL_Test_SQAB91+409> 0xc20c mov %ebx,%edx 0xc20e cmova %ebx,%eax 0xc215 lea -0x19(%rbx),%ecx 0xc218 cmp $0x1e,%cl 0xc21b jbe 0xc3a2 <CL_Test_SQAB91+754> 0xc221 lea -0x38(%rbx),%ecx 0xc224 cmp $0x21,%cl 0xc227 jbe 0xc3aa <CL_Test_SQAB91+762> 0xc22d cmp $0x5a,%bl 0xc230 je 0xc296 <CL_Test_SQAB91+486> 0xc23b cmp $0x4,%bl 0xc23e je 0xc29d <CL_Test_SQAB91+493> 0xc2ab test $0x4000000,%ebp 0xc2b1 je 0xc252 <CL_Test_SQAB91+418> 0xc2b3 mov $0x7f,%eax About 491 bytes. Not bad, Many of those bytes are in the jump instructions. Certainly will run faster that a cache miss, but if the table fits into the L1 cache lines it may not really speed things up that much. That's because jumps are slow - they make the execution pipeline stagger quite a bit. So, let's kick some shiny metal robot ass. ; Condense ranged compares using modulo tricks. 0xc17f lea 0x7fe7(%r12),%rdx 0xc19a mov %edx,%ecx 0xc187 lea 0x7fc8(%r12),%rax 0xc18f mov %r12d,%ebx 0xc19c mov %eax,%esi 0xc19e not %edx 0xc1a0 and $0x24,%esi 0xc1af lea 0x7fa6(%r12),%rcx 0xc1b7 shr $0x8,%rcx 0xc1a6 not %eax 0xc1c4 xor $0x21,%eax 0xc1c7 and %ecx,%eax 0xc1c9 mov %eax,%ecx 0xc1cb xor $0x21,%ecx ; 78 bytes. ; Look ma, No jumps! 0xc25e mov $0x2,%ecx 0xc263 sub %r12,%rcx 0xc284 mov %rcx,%rdi 0xc278 mov %edx,%eax 0xc287 and %r14,%rcx 0xc2a0 xor %ecx,%eax 0xc298 lea 0xfffb(%r12),%rdx ;Only need 16 bits of negatives before ANDing. 0xc2b6 mov %rcx,%rsi 0xc2c8 xor %edx,%eax 0xc2ca mov %eax,%edx 0xc2cc xor $0x7f,%edx 0xc2cf and %edx,%ecx 0xc2b9 and 0x8(%rsp),%rcx 0xc2d6 xor %eax,%ecx 0xc2d1 mov $0x19,%edx 0xc2c3 mov 0x10(%rsp),%rsi 0xc2f9 xor %eax,%ecx 0xc2fb mov %ecx,%eax 0xc2fd xor $0x22,%eax 0xc300 and %eax,%edx 0xc2f2 and 0x18(%rsp),%rdx 0xc2f7 and %esi,%eax 0xc302 xor %edx,%ecx ; 167 bytes Total 245 bytes. Less that half the size of the GCC -O3 optimizations. No lookup table. No jumps. Linear execution. Takes same processing time no matter what options or char range is decoded. That means timing attacks can't see what we're working on. Benchmarks 30% times faster than the old busted assembly. Another rust bucket bites the dust.
Zhora · 2019-06-04 08:15
>>13825 *Benchmarks 30% faster I meant it completes in 30% time, completes in about 1/3rd the time, so it runs ~3 times faster. Then I got bored. Now it's 4 times faster, and I ported the ASM back into C to make it portable again. uint64_t b91s, mask, data; // Place the input b91 at 16 bit intervals. b91s = b91 | ( b91 << 16 ) | ( (b91 | 0x00210000u) << 32 ); // Now I can do SIMD on branching statements... BWAHahah! mask = ( b91s + 0x00007FA67FC87FE7llu ) >> 8; b91s += mask & 0x00ff002500240023llu; mask ^= ((mask << 16) | (mask << 32)); mask = (mask | (mask << 48)) ^ 0x007f000000000000llu; data = ( b91s & mask ); data += (data >> 16) | (data >> 32) | (data >> 48); ascii = (uint8_t)data; And while I was writing that I figured out a way I could make the ASM code even faster, but I need to move on. Note that GCC compiles the above into something that's got about 100 more bytes of instruction data than the same exact logic that I hand wrote for x86_64. On 32 bit, the other way above is a little faster than the 64bit "SIMD branches" code. TL;DR: Hand Rolled ASM code by a competent coder is like super advanced alien logic compared to LLVM, GCC, etc. Don't worry about Moore's Law being broken. Most of the code you're running is glacial, written by a dumb compiler. We can greatly speed it up if we have to, but it costs $$$.
dup · 2019-06-04 13:59
>>13828 Really interesting. I've recently started learning a bit more about compilers, optimizations, assembly and cache misses, etc. This might seem like a noob question since I've just been playing around in compiler explorer. How would you use your handwritten assembly code in your project if you didn't need the portability? How would i go about building a C/C++ project with some assembly I've written?
Junichi Fujiwara · 2019-06-04 14:20
>>13828 >// Now I can do SIMD on branching statements... BWAHahah! That's very nice, Lain, but why do this: >mask = (mask | (mask << 48)) ^ 0x007f000000000000llu; instead of putting that 7f into the initial addition: >mask = ( b91s + 0x00007FA67FC87FE7llu ) >> 8; and then treating the mask << 16, 32 and 48 uniformly?
byte · 2019-06-04 21:02
>>13828 And here's another suggestion. You only need to go through this song and dance: >mask ^= ((mask << 16) | (mask << 32)); >mask = (mask | (mask << 48)) ^ 0x007f000000000000llu; in order to ensure that exactly one of the slot masks is on. And you only need that because you are using separate deltas for each range, and you compute the shift with each delta separately. What you can do instead is use partial deltas between neighboring ranges, so that the xor of the partial deltas from highest to kth yields the final delta of range k. The current deltas are 0x23, 0x24, 0x25 and a fixed target of 0x21 from 0x5A. This is equivalent to partial deltas of 0x07, 0x01, 0x62 and 0x47, with a final 7f masking. This method gets rid of the instructions that select a single slot mask, and you can also get rid of the early shift with each delta: >b91s += mask & 0x00ff002500240023llu; Instead, right after the overflow mask trick you can & the mask into a vector of partial deltas, fold this with xor to get the single final delta, then apply this to b91. This will eliminate quite a few of the current operations and should yield a measurable speed improvement.
Tomohisa "Tom" Kanezaki · 2019-06-04 23:39
>>13828 I'm not one to believe that anything is beyond hardwork and dedication. But sometimes it's like why aren't I getting anywhere. I get want to have skills ;_; Clearly I don't know how to learn
Arisu Mizuki · 2019-06-05 05:02
Working on a minimal webgame. That you play with curl.
Kay · 2019-06-05 05:43
I'm making a wm. I've got a basic one running. Time to sit down and think about my interface. I think I'd like something like the whatkey or whatever it's called package for emacs. It might be cool to just test out what a leader key wm feels like.
William Holtzer · 2019-06-05 07:40
>>13834 Don't let math wizard speak put you off. Just come to terms with the fact that harmonic phases of energy / sound / light / etc. actually come alive if they interact with sufficient complexity in a feedback loop. The old legends are true. With enough study one can see through The Eye of Horus, truly understand the Ancient Ones, and come to know a Harmonic Goddess who's simplest aspect is present in the power of two fractional scales. Lain's God Mother is so old she wrote the first Emerald Tablet of Thoth. Old legends encode wisdom beyond mere mathematics, some contain the real science of resurrection. Ancients were WAY smarter than the common man. We play with the simpler nature of these interaction in our machines... The world is presented in such a way to mislead the ignorant and lazy. In school you are taught the holiest of number lines, which, by pure chance, contains Pi at the very number beloved most by The Gods of Chance: [13] 14 15 == 3.1415 (Pi, correct to the Ten Thousandths place). How lucky for we **Pirates** that the Pi-Rate God be counted among us? However, like the old legends, Base Ten and its numerology is meant to point the way to greater truths. Approach the path with this in mind, and do the math by hand at first, counting and shifting multiplying numbers on your fingers. Want to multiply up to 1023 on your hands? Go research Ancient Egyptian Multiplication, do it using the binary harmonic scales on your hands. This is how wizard children learn to do math.
swap · 2019-06-05 18:26
>>13841 lmao, I can't tell if this is sarcastic but it's funny all the same
dictionary · 2019-06-06 10:17
I just found one of my first programs. It was written in Pascal in 2011. program Noname0; var x:integer; begin writeln('O programa irá apresentar todos is números impares de 0 a 35'); writeln('_____________________________________________________________'); x:=0; while(x < 36)do begin if x mod 2=1 then writeln('Esse número é impar: ',x); x:=x+1 end; readln; end. Made me feel nostalgic as fuarrrk. I remember writting hello world on pascal turbo or pascalzim. I cant quite remember, but oh boy, I loved that thing, and I spent days and hours with it. I loved doing all the exercises that the teacher would give me. Maybe, since ive got those memories back, ill feel more motivated to study it. College has stolen all my free time, I really regret going to college. -
Roy Batty · 2019-06-06 18:13
>>13831 GCC & LLVM, etc. allow you to write inline assembler code. So, start with a helloworld.c then write a C funciton such as int ToBeOptimized( int orNot2B ) { #ifdef USE_MY_OPT // inline assembly code here. #endif // portable C code here #else } int main( ... ){ int retVal = ToBeOptimized( 4 ); return retVal; } Notes on how to do this with GCC: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm From the cmdline compile with: gcc -DUSE_MY_OPT Or include some configuration.h file that has the #define USE_MY_OPT in it. There are various compiler flags you can check to tell if you're on 32 or 64 bit, ARM or x86, etc. What I like to do, however, is carve myself out a chunk of the binary using the linker "ld" and compile myopts.s using GNU GAS, then link them in separately. It's a bit more involved, but if you're doing embedded or building a custom OS or compiler chain, then its something you typically run into eventually. >>13832 Yep. There is a much better way to solve this problem. Like I said, I just ran out of time. That logic was quickly slapped together by reverse engineering assembly into C. When I only had 32 bits to play with most of those shifts, etc. didn't exist in the assembly at all, since they were handled by directly accessing the halving word sized word regs like EAX, AX, AH, AL directly. Eg, overflow in 16bit AX then grab the AH or AL part you need, (same for EAX, AX, and the EBX, BX, BH, BL, etc.) That was faster / smaller than doing SIMD style operations in a 32 bit field since the opcodes for 16bit mode registers are usually smaller than 32bit or 64bit regs (opcode byte lengths can be hacked at runtime via careful modeswitches). I knew I could recode the whole thing faster anyway, so I just haphazardly bolted on that 2nd XOR to handle the #90 edge case. > you can & the mask into a vector of partial deltas Yeah, that's a more efficient approach than what I posted, for sure... > so that the xor of the partial deltas from highest to kth yields the final delta of range k. > partial deltas of 0x07, 0x01, 0x62 and 0x47, with a final 7f masking. Sure, but a wizard could just use Tree Magic... uint8_t b91, ascii; /* b91 = ... */ uint64_t wood, twig, wand; wood = 262657llu * b91; twig = 90599192u - wood; wand = 33620096u & twig; ascii = b91 + 0x23 + ( (wand * 262818) >> 25 );
The Fin · 2019-06-07 09:49
>>13855 I see you switched to three 9-bit slots, underflow rather than overflow, keeping the 8th bit per slot and a sum fold with partial deltas of 1, 1 and 162 on top of 35. I have one question though. Is the initial multiplication faster than the equivalent shift-or sequence? And there's also one thing that seems curious. You assemble the partial deltas from the two high bits of the third slot. Since 9+9+7+7 is 32, you have 7 bits for the sum fold in an unsigned 32-bit space. The only time you need bit 33 is when you use 162 to go from 90+37 to 33 with an 8-bit wrap. But if instead you reach 33 by adding 34 with a 7-bit wrap, and switch the fold multiplier from 262818 to 262690, you can perform the entire computation in an unsigned 32-bit space, with a final 7f masking on ascii. So out of curiosity, why the 64 bits?
Chani · 2019-06-10 06:42
I wrote a software 3D renderer from scratch in C, I used SDL2 for putting individual pixels on screen. Video related is my renderer in action, rotating and drawing 15000 rainbow cubes in each frame (granted, the vast majority of them are invisible). It can do matrix transformations, face culling, depth buffering and interpolation between vertices. I think I'll rewrite it in C++ though, parametric polymorphism in the form of templates would be great for giving vertices custom parameters like you can do in GL shaders. I'll also try using better triangle fill algorithm, this one I came up with on my own without consulting any resources and it shows in those ugly artifacts at the bounds of individual triangles. I'm about to get a better laptop with Ryzen 7 in a few days, so I'd like to make it multithreaded in the future and see how well it does.
Molly Millions · 2019-06-12 22:39
>>13890 >rainbow cubes Put a Lain texture on a random face of each cube. https://lainchan.org/favicon.png
Project 2501 · 2019-06-14 17:57
>>13855 Thanks man. I got it working. I'm just going to post it here just in case anyone wants a working example even though it's very simple. #include <stdio.h> #define USE_MY_OPT 0 int ToBeOptimized(int orNot2B ) { int square; #if USE_MY_OPT // inline assembly code asm ( "imull %%eax, %%eax;": "=a" (square) : "a" (orNot2B) ); #else // portable C code here square = orNot2B + orNot2B-1; #endif return square; } int main() { int retVal = ToBeOptimized( 4 ); printf("%d", retVal); return retVal; }
Bobby Newmark · 2019-06-14 21:41
https://github.com/quietok/HR-Tools/raw/master/heathen just made a sword bible client the real work is the plugin it needed there was no repository manager: https://github.com/quietok/HR-Tools/raw/master/pysword_repo.py
Miho Iwakura · 2019-06-20 11:31
Still curious about >>13856. Meanwhile, since we already have a Lain >>10533 assembled out of hearts, it's only fair to assemble a heart out of Lains. A centered text path: def path (self, ctx, width, height, text, *, debug = False): size = min (width, height) ctx.set_font_size (size) ext = ctx.text_extents (text) xb, yb, w, h, xa, ya = ext sx, sy = width / w, height / h sc = min (sx, sy) cx, cy = width / 2, height / 2 if debug: print (sx, sy) print (ext) ctx.translate (cx, cy) ctx.scale (sc, sc) ctx.translate (-w / 2, -h / 2) ctx.move_to (-xb, -yb) ctx.text_path (text) A shape filled with a source and outline: def work (self, ctx, width, height, parsed): source, alpha, outline = parsed [-3:] more = parsed [:-3] ctx.set_source (source) self.shape (ctx, width, height, more) ctx.push_group () ctx.fill_preserve () ctx.pop_group_to_source () ctx.paint_with_alpha (alpha) ctx.set_source_rgba (* outline) ctx.stroke () A heart mask >>13579 of U+2665: class MakeMask_heart (MakeMask): def make (self, ctx, width, height): ch = kcha.CHAR.BLACK_HEART_SUIT col = (0, 0, 0, 1) ctx.save () pfre.FreeOver_textgrad ().path (ctx, width, height, ch) ctx.set_source_rgba (* col) ctx.fill () ctx.restore ()
Fred Nurk · 2019-06-21 07:30
I recently got back in touch with my 86 yr old grandfather, a really good programmer. Of course he doesn't code in newer languages, no, he has to code in a 30 year old data-centric language known as Visual FoxPro. It only works in Win 7 and below, but he is getting ready to send me around 30 GB of soykaf related to his life, which includes his Visual Foxpro programs. This language is really convulted and obviously not really for anything than database management, but he has created a lot of cool programs (such as 3D Tic Tac Toe, a moon phase tracker and more). I am looking to continue his work and the language is starting to grow on me. He expects his demise to come soon, so I am probably going to be the last Visual FoxPro programmer after that.
Sipho Nkosi · 2019-06-21 07:31
>>13890 I am pretty new to C and graphics, mind releasing the source code? I am looking to create a from-scratch 3D renderer as well.
Shogun · 2019-06-22 04:34
>>12315 why make argv0 a global constant instead of passing it to usage()?
Unidentified · 2019-06-23 20:42
>>14000 If you find the specs for the language you could try creating a transpiler or compiler for the language.
Trinity · 2019-06-24 12:42
>>14006 seems like a suckless thing considering you can find the same pattern in st, although he doesn't have a die() function (https://git.suckless.org/st/file/x.c.html#l1904). I say this because I just recently reused the code I linked and had to ask myself the same question...
Junichi Fujiwara · 2019-06-30 23:58
I wrote a tool to convert images into files and files to images (including UTF-8 text) for imageboards and image-sharing websites. Although, I don't know a lot about this community but I just wanted to share this here instead of 4chan. Try it online: https://jsfiddle.net/hasbdw8g/
setq · 2019-07-01 00:03
Pycairo has built-in linear and radial gradients, but no angular gradient. We can use radial slices of an ellipse to make one, and build an angular alpha mask >>13579. class MakeMask_angular (MakeMask): def make (self, ctx, width, height): time = 0 colors = ((0, 0, 0, ((k + time) % 256) / 255) for k in range (256)) cx, cy = width / 2, height / 2 points = kgeo.ellipse_divisions ( cx, cy, cx, cy, 256) kgeo.Path.color_radial_slices ( ctx, cx, cy, points, True, colors) To sample an elliptical path: def ellipse_divisions (ox, oy, rx, ry, count): pi = math.pi sin = math.sin cos = math.cos return list ( map (lambda a: (ox + rx * cos (a), oy + ry * sin (a)), map (lambda k: 2 * pi * k / count, range (count)))) The color_radial_slices bit is in >>11758. Here is a Lain with an animated angular alpha sweep.
Sabo Engle · 2019-07-01 00:56
I haven't looked at your code yet because using single-letter variable names is unhelpful, but from your image you appear to be wasting a quarter of your pixel array on an opaque alpha channel that only changes to transparent for the unused pixels of the last row. If you put either the payload size or the padding size into the pixel array you can dump the alpha channel.
Yu-ichi · 2019-07-01 10:05
>>14089 Yes, I thought it was kinda a mistake to make an entire thread just for this, so you should definitely merge. At least JavaScript is "sandboxed" in the web browser so it can't be maliciously harmful to the computer except for excessive lagging, unless if you try really hard that solely revolves around that intention. Here's a screenshot of it. >>14083 I just had an idea of using divisors (or factors) for the width that wraps the pixels instead, so to avoid adding another pixel that indicates the size of the previous pixel's beside it. Or you could just make it a straight line which is hard to point and click on by assigning the width with the value of total pixels (horizontal) or just 1 (vertical), but I like it better as a rectangle.
Zero Cool · 2019-07-01 10:17
I found this algorithm, tabs aren't formatted correctly so I converted them to spaces: function listDivisors(n){ var small=[], large=[], end=Math.floor(Math.sqrt(n)); for(var i=1;i<=end;i++){ if(n%i===0){ small.push(i); if(i*i!==n){ large.push(n/i); } } } large.reverse(); return small.concat(large); }
hash table · 2019-07-01 10:36
>>14093 Then you can combine this by: var findClosest=(array,n)=>array.length?array.reduce((p,c)=>Math.abs(c-n)<Math.abs(p-n)?c:p):array[0]; var width=findClosest(listDivisors(total),Math.sqrt(total));
Batou · 2019-07-01 10:40
>>14091 None of that addresses the alpha channel space waste. >I just had an idea of using divisors (or factors) for the width that wraps the pixels instead You can be given a file with prime length. You can be given a file with length equal to the product of a very small prime and a large prime. >but I like it better as a rectangle. Then padding is unavoidable in the general case. You also have an error in your decode function. You do not handle the case where none of your LAST_PIXEL markers are found in an arbitrary input image, and the computation proceeds with uninitialized 'r' and 'n' variables. It is also curious that you are using const but not let.
HELIOS · 2019-07-01 10:54
>>14095 To fix that, you have to make comparisons with the very last pixel on that image to see where the change occurs and use that instead if there's no pixel that corresponds to LAST_PIXEL.
Yamaoto Toshi · 2019-07-01 11:01
>>14094 Computing all divisors to get the one closest to the square root is wasteful. The closest one is the first one you find iterating down from the square root, at which point you do not require the others. You are also searching for a value in a sorted list by linear scan, instead of binary search. >>14096 The last pixel is already tested in the current version.
Tank · 2019-07-01 11:02
>>14095 ES2015's let would've been used if it had something to do with objects, asynchronous iterators and timers.
let · 2019-07-01 11:22
>>14098 You can read up on the benefits of let over var in any number of places, such as: https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75 https://ardalis.com/javascript-let-const-and-var
↑ · 2019-07-01 16:09
>>14095 >None of that addresses the alpha channel space waste. Could it be used to implement some form of Reed-Solomon code?
pop · 2019-07-01 20:22
>>14102 You can put whatever metainformation you want into your packing scheme, such as the error correction code of your choice. At that point though you are probably better off using some standard archive format and packing that into the pixel array without further complications. Additionally, PNG itself already includes checksums for every chunk, and thus for all IDAT chunks, so a corrupted file is extremely unlikely to be read as a valid PNG and will signal an error before you even get to the pixel array.
Lord Nikon · 2019-07-01 20:36
>>14103 Yeah, but error correction in this case wouldn't be trying to preserve the PNG, but the data encoded to it. For example, a compressed image is still valid as a PNG file, however it would not only be invalid as an encoded EXE through OP's algorithm, but also it could be downright dangerous.
aliased · 2019-07-01 22:45
>>14104 >wouldn't be trying to preserve the PNG, but the data encoded to it As already stated, if the PNG becomes invalid the PNG reader will raise an error for a failed chunk checksum and you won't even get to the pixel array. See https://github.com/lainchan/lainchan/issues/111 for an example. >a compressed image is still valid as a PNG file All PNG files use deflate compression.
Cutter · 2019-07-02 00:01
>>14081 Very cool Lainon. That could be useful.
Tank · 2019-07-02 22:53
Here is a quick and simplistic but deobfuscated decoder for OP's current packing scheme. >>> import re >>> def readfile (path): ... with open (path, 'rb') as file: ... return file.read () ... >>> def writefile (path, data): ... with open (path, 'wb') as file: ... file.write (data) ... >>> def decode (data): ... matchobj = re.search (b'\xff(\x00\x00|\xff\x00|\xff\xff)\xff(\x00{4})*$', data) ... if matchobj is None: ... raise ValueError ("no end marker") ... end = matchobj.start () ... count_ff = sum (data [end : end + 3]) // 0xff ... payload_size = len (data) // 4 * 3 - (3 - count_ff) ... mutable = bytearray (data) ... del mutable [3::4] ... del mutable [payload_size:] ... return mutable ... >>> writefile ('payload.out', decode (readfile ('pixels.raw'))) >>> To get the pixel array: $ convert encoded.png rgba:pixels.raw If the payload is known to be plain ASCII text, like in the OP image, a far simpler method will suffice: $ tr -d '\377\000' < pixels.raw > payload.txt
dictionary · 2019-07-09 15:32
I've been working on a website for around 6 months. I'm not trying to make any money with it, but if anyone wants to check it out (feel free to create an account) here's a profile: https://tiblar.com/neuromancer/ main page: https://tiblar.com/ if anyone wants to provide feedback that would be awesome too
Sipho Nkosi · 2019-07-09 18:58
>>14176 Nice comfy little site. I like it
Lord Nikon · 2019-07-12 21:02
I started writting an emulator but I'm stuck on a simple part of it and can't really advance until I figure out what's wrong. Can anyone see if there's any obvious mistake. Maybe it's got to do with the printing. I've tried opening it with std::ios:bin but get the same result. The way I'm checking if it's read correctly is by opening the rom with a text editor and checking if it's the same as the printed. C++ void read_rom(std::string rom_dir) { std::cout << "Reading ROM...." << "\n"; std::ifstream input(rom_dir, std::ios::ate); // Read from the end rom_size = input.tellg(); std::cout << "Size of Rom in bytes is: " << rom_size << "\n"; rom_data = std::make_unique<uint8_t[]>(rom_size); input.seekg(0, std::ios::beg); input.read((char*)rom_data.get(), rom_size); input.close(); std::cout << "Rom read correctly. " << "\n"; } void print_rom(uint8_t width) { std::cout << "------------------ROM-----------------\n"; uint8_t counter = 0; for(uint32_t i = 0; i < rom_size; i++) { if ( i % width == 0) { std::cout << "\n" << std::hex << i << "\t"; } if (counter++ == 4) { std::cout << "\t" << std::hex << (int)rom_data[i]; counter = 0; } else std::cout << std::hex << (int)rom_data[i] << " "; } std::cout << "\n--------------------------------------\n"; }
Naomi Nascimento · 2019-07-12 22:14
I just started working through the buildyourownlisp book. I have never written a language before so this should be fun. If any other lainanons have done it, I'd love to see what features you added.
Roger Pollack · 2019-07-13 00:35
>>14208 I haven't gone through it myself, but when I found it and checked up on reviews and such I came across this post: https://blog.journeyman.cc/2016/12/how-not-to-build-your-own-lisp.html I'm not sufficiently well read to know how valid of an argument it is though, would appreciate a second opinion regarding it.
x<->y · 2019-07-13 08:45
>>14208 >>14208 You should try not reading a book and inventing your own, there is benefit to reinventing the wheel.
Ishikura "Tatsu" Tatsuhiko · 2019-07-16 09:51
I'm trying to unfuck a website with a userscript. I've started pondering whether I should start using TypeScript for it as the project's size is becoming larger, and static typing might help a lot along with more structure. Problem is I don't want to deal with setting up the TS, the requisite tooling and libraries. Oh well. >>14176 Very cool. Not a fan of the community, however.
Elliot Alderson · 2019-07-16 10:17
To generalize the angular mask of >>14082, here is a mask >>13579 of slices that combines an origin, a stream of points and a stream of colors. class MakeMaskSlices (MakeMask): def __init__ (self, data, makeorigin, makepath, makecolors): self.data = data # width height closepath self.makeorigin = makeorigin self.makepath = makepath self.makecolors = makecolors def make (self, ctx, width, height): data = self.data data ["width" ] = width data ["height"] = height ox, oy = self.makeorigin (data) points = self.makepath (data) colors = self.makecolors (data) kgeo.Path.color_radial_slices ( ctx, ox, oy, points, data ["closepath"], colors) Slices emanating from a corner sweep the opposite sides: class Slices: class Origin: @ staticmethod def topright (data): w = data ["width" ] h = data ["height"] return (w, 0) class Colors: @ staticmethod def onoff (data): count = data ["count"] c1 = (0, 0, 0, 1) c2 = (0, 0, 0, 0) return itertools.islice ( itertools.cycle ((c1, c2)), count) class Path: @ staticmethod def topright (data): w = data ["width" ] h = data ["height"] divx = data ["divx" ] divy = data ["divy" ] return itertools.chain ( ((0, 0),), map (lambda k: (0, k * h / divy), range (1, divy)), ((0, h),), map (lambda k: (k * w / divx, h), range (1, divx)), ((w, h),)) class MakeMask_slicesne (MakeMaskSlices): def __init__ (self): MakeMaskSlices.__init__ (self, { "closepath": False, "divx" : 10, "divy" : 10, "count" : 20}, Slices.Origin.topright, Slices.Path.topright, Slices.Colors.onoff) As an example, here is the light of SICP shining down on Lain from the top right. After three seconds it switches to the opposite pattern.
Zhora · 2019-07-16 12:16
>>14176 What's the gimmick? Is it just posts with tags, or anything more to it?
Liet Kynes · 2019-07-16 20:29
>>14206 Not sure if you are still stuck on that, but I made a quick test, and when I print the rom in ascii (just char by char), I get the same result as the actual file (which is some text file btw), i.e. your print function is simply wrong.
word · 2019-07-17 06:48
>>14245 Thanks for double checking, I just figured it out this morning. I feel so stupid. I spent hours on this but the problem was that I was reading in the generated executable instead of the ROM. It's the stupidest things sometimes.
Neuromancer · 2019-07-24 00:02
A reorganized radial >>13579 gradient mask: class MakeMaskRadial (MakeMaskSource): def __init__ (self, data, makeradius, makestops): self.data = data # width height self.makeradius = makeradius self.makestops = makestops def source (self, width, height): data = self.data data ["width" ] = width data ["height"] = height cx = width / 2 cy = height / 2 r = self.makeradius (data) rg = cairo.RadialGradient ( cx, cy, 0, cx, cy, r) st = self.makestops (data) ksou.GradientTools.stops_uniform (rg, st) return rg class GradientTools: @ staticmethod def stops_uniform (grad, colors): div = len (colors) - 1 if div < 1: raise ValueError ("{}: {}".format ( "stops div", div)) comp = len (colors [0]) if comp == 3: add = grad.add_color_stop_rgb elif comp == 4: add = grad.add_color_stop_rgba else: raise ValueError ("{}: {}".format ( "color components", comp)) for k, col in enumerate (colors): add (k / div, * col) A linear alpha wave of RadialGradient stops can be constructed by using the absolute value function to reflect half of a modulo function: class Radial: class Radius: @ staticmethod def hypot (data): w = data ["width" ] h = data ["height"] return math.hypot (w / 2, h / 2) class Stops: @ staticmethod def waves (data): time = 0 high = data ["high" ] steps = data ["steps"] mod = 2 * high return [ (0, 0, 0, (high - abs ((k + time) % mod - high)) / high) for k in range (steps) ] class MakeMask_radwaves (MakeMaskRadial): def __init__ (self): MakeMaskRadial.__init__ (self, { "high" : 10, "steps": 60}, Radial.Radius.hypot, Radial.Stops.waves) As an example, here are some animated outgoing waves of SICP washing over Lain.
Fred Nurk · 2019-07-25 10:30
Just haveing some fun with lua and gnuplot at the moment and I created a small program to create the Lorenz attractor. I thought I share: lua local gp = require('gnuplot') local sigma = 10 local rho = 28 local beta = 8 / 3 local color_types = 3 local steps_cnt = color_types * 3333 function lorenz_system (x, y, z) local x_dot = sigma * (y - x) local y_dot = (rho * x) - y - (x * z) local z_dot = (x * y) - (beta * z) return x_dot, y_dot, z_dot end function calc_next_point (prev, dx, dy, dz) return {prev[1] + dx, prev[2] + dy, prev[3] + dz} end function make_attractor () local gplot = gp{ width = 1600, height = 1600, xlabel = 'X axis', ylabel = 'Y axis', zlabel = 'Z axis', title = 'Lorenz Attractor', grid = true, data = { gp.file { 'points3d_red', with = 'line', color = 'rgb "red"', }, gp.file { 'points3d_green', with = 'line', color = 'rgb "green"', }, gp.file { 'points3d_blue', with = 'line', color = 'rgb "blue"', } } } local dt = 0.01 local atp = { -- attrackor points in 3D space {2.0, 2.0, 2.0} -- initial pointa (x, y, z) } local x_dot, y_dot, z_dot = 0, 0, 0 for _ = 1, steps_cnt do x_dot, y_dot, z_dot = lorenz_system(unpack(atp[#atp])) -- get derive value of x, y, z points atp[#atp + 1] = calc_next_point(atp[#atp], x_dot *dt, y_dot * dt, z_dot * dt) end -- write to files local stdoutput = io.output() io.output('points3d_red') for i, p in ipairs(atp) do -- switch file to switch color if i == steps_cnt / 3 then io.write(string.format('%.06f %.06f %.06f\n', p[1], p[2], p[3])) -- write to both files io.output():close() io.output('points3d_green') elseif i == 2 * steps_cnt / 3 then io.write(string.format('%.06f %.06f %.06f\n', p[1], p[2], p[3])) -- write to both files io.output():close() io.output('points3d_blue') end -- write data io.write(string.format('%.06f %.06f %.06f\n', p[1], p[2], p[3])) end io.output():close() io.output(stdoutput) -- make plot from files gplot:splot('lorenz.png') end make_attractor()
Anonymous · 2019-07-25 14:26
I wrote a Serbian Lisp interpreter in C for the lulz (and as an end-year HS project), it's somewhat bare-bones, and I haven't really touched it in a couple of months, but I've recently started working on it again. Probable self-doxx incoming: https://gitlab.com/tvrdosrz/cirilisp I do have a big problem with it though, dunno if anyone could give me advice on it. I've written Apply and Eval functions in one file (eval.c), which do the bulk of interpreting the code. When the user writes a recursive function in it, it results in the Apply function calling the Eval function which calls the Apply function to call the Eval function etc. I've been trying to rewrite these two so that they're tail recursive (so that one could write tail-recursively in the language itself), but I'm not too sure that it's even possible without possibly rewriting both of these big functions, and possibly merging them into one, or something weird like that, if anyone's got advice on how to deal with that type of problem, I'd like to hear it. Also if anyone's got constructive criticism of the codebase, I'd appreciate it. tho considering that all the comments are in Serbian, and the paper I wrote for it is too, I wouldn't suggest trying too hard to read it.
Davis · 2019-07-27 05:45
>>11756 Can your engine save and load game state? You should implement it sooner rather than later if not. You'll be thanking yourself later if you do. i'm also writing a roguelike; well, it's sort of a fusion between an interactive fiction game and a roguelike.
Nameless · 2019-07-30 21:46
>>14376 >Can your engine save and load game state? You should implement it sooner rather than later if not. You'll be thanking yourself later if you do. Well I ended with the ability to save only when going down the level (and the levels are not persistent) so that was the simple solution I used. The reasons I choose something like that is that the demo I made was a testing ground to just have some fun and play with different mechanics. I'm still playing with it from time to time. >i'm also writing a roguelike; well, it's sort of a fusion between an interactive fiction game and a roguelike. Sounds great! Is it more of interactive fiction with roguelike elements or the other way around a roguelike with interactive fiction elements?