Rotated Lines and Hitboxes in the Browser

I came upon this particularly interesting issue the other day while building a system for basic Microsoft Paint-style drawing utilities. Functionality like drawing rectangles, circles, text and lines. In particular, I was working on generating a line drawing functionality in HTML/CSS + Javascript that did not rely on more advanced rendering techniques, like <canvas> or <svg>.

The basic approach I took involved CSS transformations, a border and just a little bit of high school trigonometry. Making use of the offsetX and offsetY attributes of the onMousedown and onMouseup events to a background layer, we can get the top-left and bottom-right points to a box that bounds our line. Not only that, but the line is drawn directly from one corner to the next.

It is, of course, possible for the line to go from top-right to bottom-left as well, but I will leave that as an exercise for the reader (i.e, you).

Using the above figure as reference, we can see that the line we are looking for is the hypotenuse of the triangle made using the width and height of the bounding box as its sides. Looking at the code that forms the above, we see the following

<style type="text/css">
#example-1 {
  width: 100%;
  height: 200px;
  position: relative;
}

#example-1 .bounding-box {
  position: absolute;
  left: 50%;
  width: 300px;
  margin-left: -150px;
  top: 25px;
  height: 150px;
  border-top: 1px dashed black;
  border-right: 1px dashed black;
}

#example-1 .line {
  position: absolute;
  left: 0px;
  top: 0px;
  height: 1px;
  box-sizing: border-box;
  width: 335.41px;
  border-top: 1px solid red;
  transform: rotate(0.4636476rad);
  transform-origin: 0;
}

</style>
<div id="example-1">
  <div class="bounding-box">
    <div class="line"></div>
  </div>
</div>

Let’s refer to the highlighted lines, because those two contain all the magic.

We’ll start with the width of the line. Going back to our basic, basic trig, we know that the width of the hypotenuse of a triangle is longer than either of its sides. In fact, it is equal to the square foot of the square of its sides.

Math.sqrt((width * width) + (height * height))

Now, we can go to the slightly more difficult task of handling the rotation. You’ll see in the code above it’s handled by the two CSS lines involving transform and transform-origin. The transform, in particular, we use a rotate function to rotate the object by a particular amount. This amount is actual the angle of the top-left point of the triangle, translated in radians (rad). Going back to our trig, we may recall the sin/cos/tan functions. We can use any of them, but for this exercise, we are going to use tan, or more specifically, atan (which is the reverse of the tangent function)

tan (angle) = opposite / adjacent
angle = atan (opposite / adjacent)

or in our case

angle = Math.atan( height / width )

NOTE: Please remember to always check your code for possible divide-by-zero errors!

Noting that JavaScript trig functions always return and accept their angles in radian form, we use the rad suffix when plugging the value into our transformation. Finally, we quickly review transform-origin. This css attribute does exactly what it purports to do – it moves the origin that transformations are performed against. For our usage, we move it to the point <0,0> within the context of the container <div> to make any additional transformations simpler (and in the case of moving from top-left to bottom-right, no other transformations are needed).

Voila! We now have a diagonal line and all the information we need to dynamically draw one onto a page in response to user input!

The Rotated Hitbox

Now we come to (in my opinion) the really interesting part. Going back to the project I was mentioning before, I came across a rather particular issue when I began trying to drag these lines around. I found that whenever I began the drag, the line would jump on the screen and then move smoothly from there. It was strange, it was unexpected and for a little bit I didn’t have any idea what was causing the bug.

Jumping to the answer, what it came down to was the way that the browser (testing across several modern browsers) was interpreting the position of the mouse event in context with the rotated item – it was using the non-transformed coordinate plane of the transformed element. More simply, while the rendering of the <div> was rotated, the offset coordinates within the MouseEvent was not.

Upon realizing this, the answer is pretty simple. All we need to do is rotate the point the same way we rotated the line, and we’re golden. However, while rotating a line relies on simple trig, rotating a point in a coordinate plane involves something a bit more complex – let’s dust off our linear algebra!

A rotation matrix is a construct that allows us to transform any point from one coordinate plane to a different coordinate plane that is just a rotation of the first. Classically, the two-dimensional version is represented as the following:

cos (angle)-sin (angle)0
sin(angle)cos(angle)0
001

By performing matrix-multiplication of the transformation matrix and the point vector (x,y,1), we can arrive at the points in the standard coordinate plane where the point *should* reside, thus translating the non-transformed point returned by the MouseEvent into the transformed version that will correlate with where the use actually placed their mouse.

The code, in JavaScript, to affect the transformation looks like this:

var x = event.offsetX
var y = event.offsetY 
var cos = Math.cos(angle)
var sin = Math.sin(angle)
var point = { x: (x * cos) - (y * sin), y: (x * sin) + (y * cos) }

And that’s it! We are now able to not only draw diagonal lines with simple HTML/CSS, but additional make use of the browser’s mouse events to handle hitboxing (instead of doing it ourselves, which would be exhausting).

Happy Coding!

Polymorphic Associations and Search Permissioning (Part 1)

A quick foreword. While this article and examples may be written specifically for Ruby on Rails, the technique should function equally well across different servers.

To set the stage – let’s say we have built a website for this new COVID-friendly world. Teachers can post homework assignments, give tests, etc. One of your stakeholders has come to you and noted they want one central way for their teachers to be able to monitor the state of all the assignments, tests and everything else active on the system.

Obviously, we need a new view of the data that can be access. Say we generate a new model that will encapsulate the idea of this view. Theoretically, the model could look something like this:

{
  homework_id: NUMBER,
  test_id:  NUMBER,
  status: STRING,
  status_at: DATETIME
}

We see that we need to include the homework and the test ids as reference, because these statuses can be applied to either of them. While this may work at first, it’s apparent the weakness – every time we need to add another item to be tracked, we need to add yet another column to the model to track that ID. The more columns we add, the more empty columns we are going to have per row and the more messy our data is going to be.

To combat this kind of situation, we are going to use a technique that Rails refers to as Polymorphic Associations. Instead of maintaining individual columns for every type of this association, we’re going to instead maintain two columns to represent the entire association. One will indicate the type of the referenced model and the other will indicate its id. (There is obviously an assumption here about single-column ids, but this scheme could support multi-column primary keys with some refactoring).

IMPORTANT NOTE – Although we are specifically discussing Rails, the idea of Polymorphic Associations works equally well in any environment, tied more with your architecture than with your server. Furthermore, the techniques outlined later to work with dynamic permissioning are equally platform independent, relying more on how we organize our search objects than anything else (but more on that later!)

Our new model looks like the below

{
  status_for_type: STRING,
  status_for_id:  NUMBER,
  status: STRING,
  status_at: DATETIME
}

In Rails, specifically, this can be indicated with an association, as seen below:

class Status < ActiveRecord::Base
  belongs_to :status_for, :polymorphic => true
end

So, in this way we’re able to gracefully link our new Status class as belonging to many other classes, i.e. Homework and Test.

class Homework < ActiveRecord::Base
  has_many :statuses, as: :status_for

  def name 
    "Homework #{self.id}"
  end
end

class Test < ActiveRecord::Base
  has_many :statuses, as: :status_for

  def name 
    "Test #{self.id}"
  end
end

Now, if we wanted to generate a Dashboard or a Calendar with a list of statuses, we could easily do so by looking up all the matching statuses from the single table, with what the status is for as a simple lookup for each row.

statuses = Status.where(status_at: Date.today)

statuses.each do |status|
  puts status.status_at.strftime("%H:%M %p") + 
       " - " + status.status_for.name
end

Search Permissioning

Let’s make our use case a bit more selective. In a school, there are multiple different types of users. There are teachers, students, non-teaching faculty, etc. It is likely that we won’t want everyone to see every status on their calendar. Sometimes, this might be because they won’t want to know about certain items but other times it might because certain items are private, and should only be shared with those who have access.

First Attempt

The easiest way to build out a system like this is to just check every item against a method that indicates if the user has permission. Say this method is called has_access?(user), where the user indicates who is requesting access.

We could them update our code from above as follows:

statuses = Status.where(status_at: Date.today)

statuses.select! {|status| status.has_access?(user)}

statuses.each do |status|
  puts status.status_at.strftime("%H:%M %p") + 
       " - " + status.status_for.name
end

I’ve put the filtering on a separate line to make each statement represent one portion of the logic.

Now, on line 3, we can see that we are looping through all the returned results to ensure that we are only outputting those that the user has the ability to see. This is completely valid and will work to solve our use case.

It is, however, also extremely wasteful and very nonoptimal. Say we return 1000 statuses that are happening in the school today, but this user can only see 5 of them. We have returned from our database 995 statuses that are unnecessary. That is a lot of extra information.

Furthermore, if we are expecting to have more than one page of results, this makes paging our results significantly more difficult, for (at least) the following reasons. (Feel free to add your own!)

  1. We cannot correlate our offsets with the page numbers. The offsets need to be aware where the last page ended. (This means to move to page 5, we must already know the offsets for pages 1,2,3 and 4).
  2. We either need a very large window, to ensure that we can fill our results, or we may need to query the data multiple times in order to actually collect all the items to fill our results
Second Attempt

Another method is to find all the Tests and Homeworks that a user has permission to access and then use those values to verify the statuses we are going to pull (as the access to the status is a function of the polymorphic association).

The code for this attempt could look like the following:

class Test < ActiveRecord::Base
  # ...
  has_many :test_users
  # ...
  def self.for_user(user)
    all.joins(:test_users).where(test_users: { user_id: user.id })
  end
  # ...
end

class Homework < ActiveRecord::Base
  # ...
  has_many :homework_users
  # ...
  def self.for_user(user)
    all.joins(:homework_users).where(test_users: { user_id: user.id })
  end
  # ...
end

tests = Test.for_user(user)
homeworks = Homework.for_users

statuses = Status.where(status_at: Date.today)
statuses = statuses.where(status_for: tests).or(statuses.where(status_for: homeworks))

statuses.each do |status|
  puts status.status_at.strftime("%H:%M %p") + 
       " - " + status.status_for.name
end

The `# …` in the code above is used to denote random other lines that may have been included previously in the classes, or any other methods that may normally find their ways into a standard Rails class.

Reiterating the idea we stated before, we can see above that we first gather all the homeworks that a user has permission for and then we gather all the tests that the user has permission for (in the above example, permission is represented as the user having an existing relationship to the Homework or Test in a relationship table). We then gather all the statuses that have a status_at of today as well as either matching an item in the homework list OR matching an item in the tests list.

The above method solve both our issues from before. Our offsets will not depend on anything other than the natural order of the response and will not need to window our responses to ensure we have “enough”.

Attempt Two and a Half

Where this method starts to look less appealing is when the list of valid homeworks or tests starts to grow unwieldy. After being in school for several years, a student is going to start to accrue a goodly amount of tests and probably a larger amount of homework. Our query is going to start to get rather large heading over the wire into the database.

Relational databases are well aware of our pain, however, and come bearing the gift of JOINs. (You may have noticed them before and either didn’t know what they were or were confused why I skipped their natural conclusion). I’m not going to spend a lot of time describing JOINs in detail, nor going over their pros and cons, but I will simply note that a JOIN is a way for our database to combine multiple tables so that one query can be issued across all of them.

Because the query is a bit nontrivial, I am going to write it out in SQL.

SELECT statuses.*
FROM
  LEFT JOIN homeworks ON (statuses.status_for_type="Homework" AND statuses.status_for_id=homeworks.id)
  LEFT JOIN homework_users ON (homework_users.homework_id=homeworks.id)
  LEFT JOIN tests on (statuses.status_for_type="Test" AND statuses.status_for_id=tests.id)
  LEFT JOIN test_users ON (test_users.test_id=tests.id)
WHERE
  statuses.status_at = TODAY() 
  AND 
  (test_users.user_id=OUR_USER_ID OR homework_users.user_id=OUR_USER_ID)

Most of the heavy lifting here is how we set up our JOINs (specifically, our LEFT JOINs). We see that we are connecting our statuses to our users through their connection with either a Homework or a Test. The two paths we are targeting are “status -> homework -> homework_user” and “status -> test -> test_user”. One we collect all of that information, it’s just a simple matter of whittling down statuses that occurred today and statuses that match our user as either a homework_user or a test_user.

The reason for LEFT JOIN is because of that big “OR” on line 10. A homework status will not be connected to a test and a test status will not be connected to a homework, but to satisfy our needs, we’ll need both of them. A LEFT JOIN means that we will collect ALL of the “left” side of the join, whether or not there is a matching item on the “right” side (but we will not do the same in the opposite direction). It’s best understood using Venn Diagrams, which w3schools does an amazing job showing in their tutorial on the subject.

And with that, we have a single query that gather only the relevant statuses for our user, no matter how many items are added into the system.

Mission Accomplished…

… but not entirely. There is still one big problem with the technique. In order to permission properly, our query needs to not only be aware of all the different types of objects a status represents but also how they permission themselves. For our example, we used a rather simple permissioning scheme that allowed us to solve this in a simple (albeit long) SQL query, but there’s no assurance that all permissions will be as simple.

Say, for example, we didn’t have the test_users table, but instead were expected to permission based on the role of the user, the classes they may have taken or taught, and the year they were involved with those classes. All of a sudden, our JOIN table becomes significantly more complex, pulling more and more tables into the mix.

But even that doesn’t address the following problem: What if we wanted to add statuses to class projects? There’s no reason why we shouldn’t have that status to show up with all the other statuses. But, for that to happen, every area we pull our statuses would have to be aware of the existence of this new polymorphic relationship and rebuild themselves accordingly, when that shouldn’t be their responsibility. It should be the responsibility of the Project Status to permission itself!

In my next post on the subject, we will explore how to solve this dilemma and create a status solution that will seamlessly scales to any number of “status_for” relationships.

A Journey into Python: **’ing your Arguments (and Dictionaries!)

A quick note before we start – the ** in the title refers to a double splat operator, not any kind of indecent language. That being said…

Repeating function calls with the same arguments is not the best programming practice. In fact, it’s something I am constantly working with my team to avoid. Sometimes, it is hard to avoid it when you’re writing something small. Or, alternatively, your function arguments are mostly the same, with just a couple of differences.

I’ll give a direct example from some code I am working on.

try:
  time.sleep(10)
except BaseException as e:
  cleanup_config_file(path=config_path, unique_id=unique_random_id, command_length=command_length)
  raise e
  # End here if there is an error

cleanup_config_file(path=config_path, unique_id=unique_random_id, command_length=command_length)

Important Note – Yes, I know that this is more modernly and pythonically done with a with statement, but going through the trouble to build up a class in this <200 line script seems excessive.

You’ll note that I’ve already DRY’d (Don’t Repeat Yourself) up the code already by wrapping whatever is inside cleanup_config_file into a function elsewhere. Even so…those function calls are pretty excessive.

That’s where the handy, dandy double splat operator comes in… well, handily. You can use it to send a dictionary into a function as the arguments. Without further ado.

cleanup_args = { "path": config_path, "unique_id": unique_random_id, "command_length": command_length }
try: 
  time.sleep(10)
except BaseException as e:
  cleanup_config_file(**cleanup_args)
  raise e
  # End here if there is an error

cleanup_config_file(**cleanup_args)

So, if you can’t be bothered to write a class with a proper __enter__ and __exit__ methods, then this is a lovely way to simulate a with. 1

This can also be useful if you have a lot of similar arguments, but a couple of varying ones. For this example, say you have written a function that is signing your team up for a conference.

conference_sign_up(first_name="Peter", last_name="Gibbons", company="Initech, Inc", address="123 Corporate Drive", city="Anytown", country="USA")
conference_sign_up(first_name="Michael", last_name="Bolton", company="Initech, Inc", address="123 Corporate Drive", city="Anytown", country="USA")
conference_sign_up(first_name="Samir", last_name="Nagheenanajar", company="Initech, Inc", address="123 Corporate Drive", city="Anytown", country="USA")

… which is a lot of text. Happily, we can use our **’s to make this a lot simpler.

For bonus points, we will also use them to help us quickly merge dictionaries, making the code much slicker.

office_details = { "company": "Initech, Inc", "address": "123 Corporate Drive", "city": "Anytown", "country": "USA" }
conference_sign_up(**{"first_name": "Peter", "last_name": "Gibbons", **office_details})
conference_sign_up(**{"first_name": "Michael", "last_name": "Bolton", **office_details})
conference_sign_up(**{"first_name": "Samir", "last_name": "Nagheenanajar", **office_details})

And finally, for super extra credit (because we should always be refactoring, let’s throw the repeatable details into a structure we can iterate on.

office_members = [["Peter", "Gibbons"], ["Michael", "Bolton"], ["Samir", "Nagheenanajar"]]
office_details = { "company": "Initech, Inc", "address": "123 Corporate Drive", "city": "Anytown", "country": "USA" }

for person in office_members:
  conference_sign_up(**{"first_name": person[0], "last_name": person[1], **office_details})

Hope this helps everyone write cleaner, unclean code. Happy coding!

As referenced by the only footnote above, I just want to direct anyone who wants to learn more about the with operator to this article on effbot.org.