we had the GitHub co-pilot fixing some minor bugs. So it's actually working well if you have your eyes open and don't move much in terms of tracing as well. So that's the green line. I don't know. Yeah, there seem to be some, so we're getting, we got all the code into GPT-4 and because we need some broader context for this, we also have two descriptions for the application. That's a more recent one. That keeps the BIS-ing a bit. Hopefully we'll fix that eventually. Let's say about commercial. It's obviously only experimental prototype to make sure it says no commercial use, no medical use, so on and so forth. Okay, so this is Flask application. So yeah, we're using Flask, we're using eye tracking as a CV2. So that's working fine for the eye tracking. Yeah, we're using media pipe. So that's the main library and then NumPy as well. So we're getting those frames. I think it was from GitHub Copilot was able to do this for us quickly. We did this line later. Well, there's obvious difference between eye tracking and pupil tracking. So it's a whole different ball game. So we have the code in GPT-4. GPT-4, we had some issues with it. We had an OR error, which it actually fixed, but then we improved the frame generation function as well. That's actually checks for empty frames now. Because if I move outside before it used to just fail, just drop out, now it keeps going. It should have a print out of empty frame somewhere. Now it's still dropping out. It's the same error, yes. Yeah, it doesn't seem to be able to sort this one out. No, it's actually, I don't know, it is the same. Yeah, empty, like an empty array. Empty array, okay, we might deal with that one later. Yes, obviously one eye is jumpier than the other. And one good thing about GPT is that we actually can generate the images for it. Let's do that quickly. Do a few, just pop them straight away in. Yeah, GitHub co-pilot obviously cannot do this. Which there was a video, I wonder if you can upload a video of it working. So essentially trying to get it fixed jittery business for us. So we have some jitter in the pupil detection, eye detection working well, but the pupil is getting not detected very well. Can we also go over an ability to display the whole processing through turning the image into grayscale because that might need the tweaking, the level of grayscaling. Can you also explain how the pupil is being currently detected? Do you have all the code, several factors? Yeah, it's pretty good that this explaining these things, much better than a university lecture, for example, that might, well, mainly have hundreds of students to take care of and also not be the most patient teacher. So doing the grayscale conversion, just read that. The region of interest, ROI, around the eye is converted to grayscale, which reduces the complexity of the image and helps in detecting the darker regions that represent the pupil. Yeah, we wanna know how that exactly works. Like can we actually view the grayscale image somehow or potentially not overlay, but maybe a button to provide an option to see the grayscale image. Half circle transform, the adjusted grayscale image is used to detect circles that represent the pupil. It might not always find a circle, especially if the contrast is not optimal or if the pupil is not the most prominent circular feature in the ROI. Yeah, can we also visualize the hue circle transform? Darkest point fallback. If no circle is found, the code falls back to locating the darkest point in the ROI, which is assumed to be the pupil. ROI size, make sure the size of the ROI is appropriate. If it's too large, it might include non-pupil areas causing instability. If it's too small, it might miss the pupil entirely when there's movement. Okay, with the ROI size, I cannot make sure that the ROI is actually the blue square around the eye. Yeah, I'm not sure about the temporal smoothing that reduced the quality, the detection quality, the speed is suggesting to make the algorithms slower, is it? Yes, displaying a second window sounds good. Can we, are you gonna be generating the code or get the prompts for GitHub co-pilot to do it? Can we also display the current frame rate? Now, the other thing that I would like you to touch on is the fact that we actually have two web cameras, a position side by side, would it help that each camera will be doing detection on each eye? Yeah, might as well. It doesn't sound like it's gonna generate any code. We might as well get the GitHub co-pilot to do it. All right, because the actual video footage is displayed using something else. So gray scale will be happening in the eye tracking pie. So we have, obviously, our index HTML, by the way, it currently has two descriptions of this application and both of them are pretty bad. So we eventually will get the GPT-4 to rewrite that I think originally it was done by co-pilot. That's why the quality is not great because it's not looking at the overall context of the whole project. So it's just looking at the individual files. You can get it to look at the whole context, but for example, if I use this to S-prones, in theory, it should find where the code should be changed or edit. So it's determining the workspace structure, deciding which information to collect, right? So in find pupil, how are we doing IM show in here? No, the find pupil is in the eye tracking pie pile, but what was the change? So it's creating two windows, one showing the gray scale and one showing the circles. I thought it could overlay the two can the circles be overlaid over the gray scale in one image? I'm not sure if it, yeah, you see, now it's looking at the specific lines of code. Well, so we were in the correct region of the code, so that's fine. And single window showing the gray scale ROI with the circles overlaid. We need to call CV to weight key one. So is it waiting for a keyboard response or something to update the window and handle the user input? Why? It's returning the same stuff. By the way, if you haven't checked out by any cares.com, please do so. All the current tools, which is the waveform, a feature extraction detection, and webcam eye tracking will eventually come up on this site as well. Currently we're just testing them locally, but we'll try to share it with you as quickly as possible. Just has to do something useful. Doesn't have to be perfect. And now a thing, by the way, that we are doing looking at this data set from the Childmind Institute was a healthy brain network. That's what the data set is called. There's about 1000 recordings from 1000 patients. The data set is publicly available under Creative Commons license, which is great for us, because this is what we do as well. Apparently I didn't download the correct file, just looking at one subject, but then realized it doesn't have the full phenotopic file, even though it doesn't make sense. Anyway, I'm still trying to figure it out. Back to this quickly, just trying to improve on this eye tracking system. We're selecting the find pupil. Might as well just comment it out, just so we, our kit is not working at the moment. So I'm not actually using it, or not properly using it, right? And this will, yes, when you update that file, it gives a fatal error, which ideally we will not put in the month, we just have to rerun the application and the window is a separate window and it's not updating. And that's obviously running in Python. Yeah, so that's a GitHub co-pilot. Unfortunately it doesn't have the full context for the whole, or everything we are trying to do. So let's just go back to GPT-4. To confirm that the blue squares are indeed being drawn around the eyes as intended, you should be able to see these squares in the live video feed your application provides. If they're not visible, ensure that the coordinates and dimensions used to draw the rectangles using CLE2. Rectangle are correct and that they're being drawn on the frame that is being displayed. This is actually quite important. And let's check the blue rectangle squares. Yet they are not the ROI, are they? If the pupil detection sometimes jumps to the eyelids or other dark regions, it's a sign that the ROI may indeed be too large. You need to adjust the size to better fit the actual eye area. Temporal smoothing will average the detected positions over several frames, which can help reduce jitter. While it might slightly reduce the real-time nature of detection, since it's averaging over past positions, it generally won't make the algorithm slower. It's a trade-off between smoothness and real-time feedback. And it's okay to remind it to be slower, it's actually seem to be jumping around too fast at the moment. To display the current frame rate, you can calculate the number of frames processed in one second and display this on the video feed using CD2 for text. Yeah, we do want to do that. Because there is a chance that I'm not in the correct file. I just used the at workspace. I want to do this bit. We want to display the frame rate onto the footage and generate frames. Yeah, which is, I wasn't the wrong file. Should this display the frame rate on the top left corner of the video feed, it will be updated each frame. Yeah, and this, well, that's the thing. It would be a different to the frame rate of the camera. Let's just double check that we don't have any placeholders in that function. Doesn't look like. Right, so we have the frame rate, which is good. It's 30, 31, whatever. Yeah, this one should be showing us the grayscale ROI. And that's wrong. Well, because first we don't want to display it in Python. We want to display it on the front page or keeps opening that bit. Yeah, when I get rid of that, go back to the previous find pupil function to rerun the application. Right, I have to do that bit again. The frame rate is crucial in eye tracking because it dictates how smooth the tracking will be and how quickly the system can respond to movement. Higher frame rates can capture more data points and provide a smoother tracking experience. For eye tracking, a camera that can provide a consistent 30 FPS or higher is usually recommended. Yeah, we're using 30, or why it's dropping down to 27 or something. Using two web cameras positioned side by side could potentially improve detection by having each camera focus on one eye. This could provide more data and reduce occlusion but would also double the data processing requirements. The algorithm would need to be adapted to handle input from two cameras and merge the data accurately. Yeah, we might do it as a potentially separate tool, like a tool update. A dealing with one camera is difficult enough. For the changes in visualization features you want to implement, you can modify the process underscore frame function in your Python code. For example, to display the grayscale image. So where am I actually doing that? I'm exactly sure. And for displaying the circles detected by the half circle transform. So what did that? No, it wasn't doing it. That was the it was plotting a separate a separate window. Remember to update the code where necessary to include these changes and ensure that you have CV2, destroy all windows and the appropriate places in your code to handle the display windows correctly. Lastly, regarding GitHub co-pilot, it can certainly help generate code snippets based on your prompts. However, you'll need to feed a specific tasks or issues you're facing and it will provide suggestions based on its training. It's a powerful tool, but remember that its suggestions should still be reviewed and tested by a human programmer. Now that's fine. So can which so currently the suggestions there to use CV2 I'm show is fine but I do want to display the extra window on the front end. So the end user can see how the pupil detection actually working. Also any idea why my FPS dropped from 30 to 15 that would be good to know. I suspect we'll have to transfer more data to the front end, which is fine. I actually wanted for everything to be done on the front end as well. That would be great because then I don't have to use as much electricity. So I want to do it in this main JS that's currently only 50 lines of code as opposed to 85 in eye tracking and another 70 in the flash application that might need restructuring of the whole code so see how we go. Displaying the pupil detection process on the front end for the user to see is a bit more complex than just popping up a window with CV2. I am show which only displays on the server side. To achieve this in a web application you need to send the process frames back to client browser. Yeah, this is not ideal, is it? I wanted to do the whole processing in JavaScript. I wasn't actually listening. I did suggest to add a button which will toggle between the real view and grayscale with the circle, hue, circle visualization. I'm thinking restructuring the whole thing so all the image processing is happening in JavaScript. I mean, let alone this thing is not working very well as it is. Unless I do this then it's working better. Yeah, we want to see how the grayscale stuff might need tweaking. Now it's back to 30 FPS. So obviously we can get 60 FPS from two cameras. I mean, we can get a GoPro or something. I don't know what's it's a maximum frames per second will be like a thousand or so. I wouldn't mention. Increased processing load. If you've added more processing steps, like the pupil detection visualizations, this can significantly increase the computational load and decrease the frame rate. Network bandwidth. If you're streaming video, network bandwidth can be a bottleneck. Network bandwidth is insufficient for the stream's data rate. Frames will be dropped to compensate. So how does it currently? Yeah, currently it's not great. Is it because we're streaming, because you will be streaming the footage to the website? Because in comparison if you look at let's close this for a sec. If you look at the hand gesture thing, this one is doing everything with the script. It was a false detection. We'll do long ones, short ones. And it's in music, musical. That's what a head scratch sounds like. The good thing about this one, when you use it, which is already up there, can try it out. I do not use electricity, so JavaScript. And I also don't have to post anything on GitHub, because JavaScript just should be available in the browser. So you can just download the source code. So probably we'll try and do the eye tracking in the same fashion. So I can try this one out, especially because it has some advertisement. So you'll be supporting the project. Now get back to this. We might need to restructure the whole thing. Yeah, originally we told it to do a Flask application. That's why it's heavily relying on Python. Generating frames. Yeah, there was some error business when there's no frame, well, no person, no eyes in the footage. It was failing. What's it giving me? Who? It's something to do. The camera is it. So one camera is not being used. No, it's actually working. I don't know what's all this. Well, right. The other thing is when you do use JavaScript alone, then you are relying so I can guarantee that it's going to work at all on your machine because well, I'm running a GPU and everything. So I don't know how quickly if at all it will work in your browser on your machine. Yeah, I know the music generation doesn't work well on the mobile. So I have to use those equivalent JavaScript libraries or running this. I'm not sure if it's going to work at all. Ideally, I will find some sort of balance between back and front end. Let me know what you think. Is it possible to move most of the processing as much as possible to the front end? So is the equivalent JavaScript library that can do eye tracking? Eye tracking? Eye tracking? It's hopeless. We ideally would like to display the output, the result of the eye tracker and all the processing stages a grayscale, hue, transform, so on and so forth on the front page on the HTML. It's not a good sign when it's thinking that long. Tens of low being overkill for this. Moving processing to the front end can definitely help distribute the computational load and may improve the performance of your application. For eye tracking in the browser you can use JavaScript libraries that are designed to work with facial and eye detection. The library is TensorFlow. JS with models like blazeface for face detection which you can use as a starting point for eye tracking. Yeah, because I don't think a media pipe does eye tracking anyway. Yeah, this eye tracking module. Where is it even coming from? Well, right, that's the that would be the media pipe stuff. No, sorry, that's there. That's how little Python I know and that's importing the eye tracking pie and the eye tracking pie using media pipe and media pipe just does it detects the eyes not the pupils. Yes, we don't want to just display it in I am sure because that would be only in the back end. It won't be accessible to you. Yeah, this is a very high level approach. Doesn't have any face detection. Use a pre-trained TensorFlow JS model to detect the face in a video stream from the webcam. Okay. Eye detection. Once you have the face landmarks you can locate the eyes and create a region of interest around them. Grayscale conversion convert the eye to grayscale using JavaScript canvas API. Yeah, probably really something like that exists but it will be really good for us to display the whole processing ideally on the same window. But, let me if another window is necessary it should be fine to pupil detection. Use image processing techniques to detect the pupil within the eye. You might have to implement the logic for this manually as there may not be ready made JavaScript library for pupil detection that's a straight forward as OpenCiv's half circle transform. pupil detection. Use image processing techniques to detect the pupil within the eye. You might have to implement the logic for this manually as there may not be ready made JavaScript library for pupil detection that's a straight forward as OpenCiv's half circle transform. I think I'm wondering if it still should be a flash application but because eventually we might do something on the back end. But yes, rely on JavaScript as much as possible. Visualization. Draw the detected eyes and pupils on the canvas and update it in real time as the video stream processes. Optimization. Since JavaScript runs on the client's browser, you need to ensure that the code is optimized to run efficiently without causing lag in the user interface. Right, that's kind of not up to me. I'll be testing it on well, my machine which is a beast it's a 3090ti GPUs and so forth and Intel i9 but then could also test it on a standard laptop as well. That's as much as I could be doing testing you'll have to let me know how this would work for you. To display the output and processing stages on the HTML page, you've set up multiple less than canvas greater than elements or less than video greater than elements that are updated with the various stages of processing original video, grayscale image, eye detection bounding boxes, etc. Keep in mind that while moving processing to the front end can reduce server load, it also places more demands on the client's device. This approach assumes that the end-users have sufficiently powerful devices to handle the real-time processing. You would then have a JavaScript file, eye tracking, JS that handles the TensorFlow, JS model loading, face detection, eye detection, grayscale conversion, and kubel detection. This file would also be responsible for updating the output canvas with the visual results of these processing stages. Yeah, I like this approach better considering I'll be paying less for electricity. Remember to check the privacy implications of processing biometric data like eye movements on the client's side, as well as ensuring that your application is compliant with any relevant data protection regulations. Alright, so if the last point currently with the Flask application does it mean that we are sending the video footage onto the server? That's not ideal if that's the case. Now, I'm not sure if we should start fresh with another version of this application. Shall we still keep at the Flask application just in case we do need to do something on the server? However, rely mainly on JavaScript code. Also, ideally we would like to do everything in one window, but if two windows are necessary for displaying the original footage and the grayscale with the hue transform circle transform then go for it. By the way, don't mind you to be a little bit funny if you feel like it. Yes, in your current Flask application setup the video footage is being sent from the client browser to the server for processing. This isn't ideal if you're dealing with bandwidth issues or privacy concerns since raw video data is quite sensitive. Yeah, we don't want to do that. We definitely get rid of this current Flask application the way it works is sending the video footage onto the cloud onto my server. We do not want that. Keeping the Flask app and adding JavaScript for the heavy tracking of eye tracking can give us the best of both worlds. We get to keep the server for any necessary back-end tasks while our floating real-time intensive processing to the client side. Yeah, that sounds better. The tracking. JS file will handle the capturing of video from the webcam, face detection, eye detection, and people tracking. Unfortunately, I can't whip up an entire library's worth of code right here, but I can guide you on the structure. I'm sure it has no trouble generating the whole code. But yes, we will do GitHub Copilot considering we have those 40 messages per 3 hours. We don't want to overload GPT so we'll be using Copilot as well. So it's kind of good that it's provided the doesn't have, ah, yeah the video footage from camera. So let's close this one for a second. By the way, if you haven't checked Barney Chaos yet, please do so and don't forget to provide your feedback. Everything we're currently doing eventually will go on this site as well. How do I actually get Copilot to start developing? For simplicity and a seamless user experience, we aim to keep everything in one window. However, if it turns out we need a pop-out window to properly show our BraceGal wizardry, we won't shy away from it. After all, sometimes you need to open a new window to let some fresh air in. Ah, you're actually funny. Not too funny, but just funny. In conclusion, you're now equipped with a blueprint for turning your application into a front-end powerhouse with a little server-side magic kept in your back pocket for when you need it. Keep the server lean and mean, ready for action and let the client browser do the heavy eye-lifting. Time to get coding. Okay, can you list all the files that we need, all the folders and the project structure and can you provide the whole script for each file separately? I don't mind you having templates for GitHub Copilot to fill out but I need you to generate the whole code still. Also, hopefully it will be working better than what we had in the Python Flask application that we would not be using anymore. So I assume I don't need the eye-tracking Python file and also do I need to separate the main JS or tracking JS is the main and only JavaScript file? Yeah, so that's what we had before and this is the new structure we only have one JavaScript requirements file we have this info file but it's okay, doesn't know about it call it whatever, doesn't matter for now Here's an outline of the content for each file. So we can get rid of this one and we do not have a main JS we're getting rid of this one as well so we only have HTML, tracking JS and the app. Why? Hopefully this will just remain empty because I don't actually need any data to be sent to my server I want you to be able to do the eye-tracking in your browser keep your data secure on your own machine sounds like a good option so requirement file just have the flask, why is it a different version to what we had before so we won't be using media pipe and openCV Python anymore just check the Python code this will be simple, as simple as possible alexhdml should be straightforward as well using these two libraries and this is the tracking JS text, base, eyes draw the texture video element tracking, JS will be your main and only JavaScript file containing the eye-tracking logic that's good so we got rid of main JS file since we are moving the processing to the client side you don't need the eye-underscore-tracking-python file anymore make sure you have TensorFlow JS and any other required libraries included in your HTML file, as shown in the index HTML you might need additional libraries or scripts depending on how complex your eye-tracking logic gets and what features you decide to implement make sure these files are not made up they actually have the code copyright, Google that's okay we're essentially all working for Google now this setup assumes a simplified model where all the heavy processing is done on the front end the flask service role is minimal mainly serving the static files and templates remember that implementing a full-fledged eye-tracking system in JavaScript can be quite complex and may require additional libraries and a lot of fine-tuning okay I want to access the user webcam white full-pilot can you just do it no why not a GitHub core pilot I'm like complaining to about another robot to this robot okay GPT-4, can you help me um GitHub core pilot is misbehaving it does not want to generate the code um can you do something just generate the functions yourself like streaming the video to the front end and the areas use a model to detect faces and find the eyes within the face then draw the textions on the canvas this could be a bounding box for the eye region maybe make sure it's not too large and then we are missing a bunch of functions we should have had the hue transform that will find the circles or you're suggesting a different way of doing it so that's the overall thing works at all now I also have the camera being taken taken over and should be settings of this page should be like a camera icon, I don't see it I know it's being taken over by something I think we are getting stuck with this one, might move on um to the fuzzy logic stuff so it won't be making much progress here alright, it sounds like github co-pilot might be acting a bit like a stubborn robot so let's roll up our sleeves and draft some code to get you moving I'll provide you with more fleshed out functions for the tasks you've described remember that these will be high level functions and you'll need to fine tune them to fit your application perfectly guess we have yeah, that's the flow js and blaze face that's a good name loading a model not creating a model should definitely better than what we currently have github co-pilot didn't want to generate the code I don't know why the half circle transform specifically is not available in tensorflow js or blaze face however, you can attempt to detect the pupils using a different approach, like analyzing the grayscale values within the eye regions and looking for dark circles this would involve custom code and a good understanding of image processing techniques in javascript I'm sure there is no a javascript code for library or something for detecting pupil or I mean if there is no huge circle transform surely there is a grayscale transform that should be available so currently we are doing we're starting the video stream detecting the face extracting eye regions drawing the eyes okay, that's not enough is it yeah, I'm going to detect the pupil are you going to generate the whole function or detect pupil eye region let's see if co-pilot woke up no don't understand how it works let's try shit generate this function okay, kithub co-pilot actually doing this return the darkest point we are not using it at the moment the function creates a canvas draws the eye region on it converts the image to grayscale and then iterates over the pixel data to find the darkest point and returns it as an x, y coordinate object that's interesting but it's not currently being used is it it's not used just pop the whole code into a GPT yep so now they compete with one another turn the text to a speech to test text for a sec so co-pilot generated it changed the detect faces function sometimes it's actually quite handy when it's providing links not at the moment the detect faces function is currently not being used in the provided code sorry the detect pupil is not currently being used good code in the detect faces function after you extracted the eye regions is how you could modify the text faces and what did the GPT say as well as handling the grayscale transformation and drawing everything onto the canvas here's a more complete example of how you might modify the detect faces function to include pupil detection okay so let's do different functions I cannot trust the GPT for a more than co-pilot but happy to try both so both eventually drawing left and right pupils GPT for code makes this prediction as well at the waits for the model estimate faces and maybe co-pilot code is better currently I don't have anything running because we decided not to continue with the flash application that we had so we rewriting the whole load started from scratch essentially so we definitely would not need that and it said another function which is similar to what GPT or did GPT for also has the draw face which co-pilot didn't suggest at all now the other thing is we have we also have a problem so we have two webcams connected to machine one is being used it can understand what I'm trying to do well one of them is being used by something and to be able to use GPT for sec on Ubuntu I have two webcams connected a one is being used legit the other one is being hogged by something else can I check what it is and reset potentially both cameras to check which process is using your second webcam you can use the LSOF command short for list open files open a terminal and type replace step video one with the path to your second webcam this command will show you which process is accessing a webcam if you want to reset both cameras you can try restarting the webcam sources or unloading and reloading the webcam kernel modules here's how replace less than module underscore name greater than with the name of the webcam kernel module you can find the module name by running lsmod grep video it seems like the webcam kernel modules are loaded properly the UVC video module is responsible for handling USB video class UVC, combined devices which includes most webcams since both webcams are detected and the necessary modules are loaded you can try restarting the webcam service to see if it resolves the issue with the second webcam if the second webcam still doesn't work after restarting the service you may want to check if any other applications or processes are using it by running if you identify any processes using a webcam you can terminate them or close the applications to free up the webcam for the uses additionally make sure that the second webcam is properly connected by any other hardware or software first, let's try restarting the Udo service, which manages device events then, you can try reloading the UVC video module, which handles the webcam these commands will unload and reload the UVC video module, essentially resetting the webcam driver after running these commands, check if both webcams are recognized and available for use if the second webcam still doesn't work, you may need to investigate further to identify any potential conflicts or issues with the hardware or software configuration it seems that the UVC video module is currently in use, which prevents it from being unloaded and reloaded in this case, you can try stopping any processes or applications that might be using a webcam before attempting to reload the module again it's kind of hopeless which camera they have to when they have the same names doesn't help as a one of the cameras just gets stuck that doesn't work get this error in shower script as well we have an event listener let's show we're doing this already aren't we oops don't actually do that it's the main function don't have an event listener still don't have an event listener do we need an event listener here in this function okay can you modify the function as needed what's an ESP32 cam module copy from the chat there's something wrong with something wrong with my camera in general so it works no, that's the frozen one that I have in the stream IOT run away from anything called IOT but need a server for it what? we want to do it in JavaScript only so that doesn't seem doesn't seem right let's do it in a simple way kind of similar to what we have here is this working yeah so that's brought this video brought to you by well no it's not sponsored so we closed we closed that should be as simple as this and that one JavaScript alone that works okay so I don't know why this one doesn't there is no that's 3.5 closed that oh god why this window is so funny anything wrong with this code we do not have the video footage displayed can you also check the html and the python code yep I see you're looking to get everything tied up nicely let's walk through each part of your code to ensure they're all set to work together harmoniously your html is mostly set but I notice you're missing a less than video greater than element to display the webcam stream you need to add it so that the video element in your JavaScript has a source to play from the auto play and plays in line attributes ensure that the video plays right away and in line on the web page respectively the python code looks good it's serving the single html page you have and should be working fine just make sure you have the static folders set up correctly in your flask project structure so the tracking js file can be served without issues there are a few adjustments needed in your javascript code the star video stream function is not called anywhere after the model loads you should call star video stream within the main function before setting the interval for detect faces the detect pupil function seems to be attempting to draw on a non-existent i region you need to get the actual pixel data from the video feed this would involve creating a new canvas element or drawing on an existing canvas then cropping to the i region based on the landmarks the pupil detection logic is sound in theory but it does not account for the context of the eyes within the entire video frame you need to calculate the exact coordinates of the i regions within the full frame to crop them accurately let's fix the call to the star video stream in the main function remember the pupil detection through the darkest point method is a simplified approach and may not be robust in various lighting conditions or if the user is wearing glasses in a real world application you would likely need a sophisticated method possibly involving machine learning or more complex image processing techniques finally make sure your web server is set up to serve the static folder where tracking js resides this is typically done by setting the static underscore folder parameter in your flash cap or by placing your static files in the default static directory this is my eyes funny they move in and out okay so obviously there's no pupil detection what did I say about the pupil detection I wasn't listening and a quick fix for the detect pupil function to clarify the eye region remember the pupil detection through the darkest point method is a simplified approach and may not be robust in various lighting conditions or if the user is wearing glasses in a real world application you would likely need a more sophisticated method possibly involving machine learning or more complex image processing techniques okay this is already doing this isn't it so what's wrong with this function and how do you suggest changing it there it does return the x y coordinates and brightness levels as well can you explain the function detect pupil that you've provided is based on a reasonable approach to find the darkest point in an image which is assumed to be the pupil the function however has a few issues that need to be addressed eye region extraction the eye region parameter appears to be a placeholder for this function to work eye region should be an actual image it works at the eye you need to extract the eye region from the video feed first which involves more steps than just passing a parameter canvas manipulation the function creates a new canvas element every time it's called this is not efficient especially if it's being called frequently in a loop it's better to create a single canvas element and reuse it grayscale conversion the grayscale conversion loop is correct but remember that this alone does not find the pupil it's just the first step in processing the image to make the pupil usually the darkest part stand out more clearly darkest point calculation the function iterates through every pixel to find the darkest one which is an intensive operation it's important to note that the darkest point may not always be the pupil especially if there are shadows or other artifacts in the image here is a revised version of the function with some conceptual fixes to use this function you call it with the eye coordinates extracted from the landmarks provided by the face detection model and the video element from which the frames are being captured a few things to keep in mind this function now assumes that the CTX is the context of a canvas element that has the same dimensions as the video element this canvas is used for image processing and is not necessarily the same canvas where you draw the tracking results the darkest point detection might still pick up false positives if there are reflections or shadows more sophisticated methods might involve thresholding the image to isolate the pupil or even using machine learning based approaches performance can be an issue especially if you're processing high resolution video you may need to downscale the image for analysis or use web workers to process the data without freezing the main thread as well it's not much different except that one eye is really jumpy now am I calling it correctly video element not using the video element am I because previously we didn't have a video element can you fix the detect pupil call the way this function is being called it has another variable as an input let's see if github copilot can do it how's it talking about detect faces we need to update how detect pupil function is being called are we inputting the model now it's the video element oops am I calling it model it's the video element left pupil let's comment that out quickly it's loading forever it's a bit funny like this what's it trying to do it's bad good thing about a gpt as opposed to copilot is that we can actually we can bombard it with stuff we can add an image to it that it will surely not ignore and we can ask it to fix the following code that it will surely do perfectly well there is an issue with how the detect pupil function is being called now after it was changed can we fix that and any other suggestions to improve the pupil eye detector based on the image that I just loaded that I just uploaded there are two images uploaded please check making suggestions as to how to improve the code yep going in circle with this one my ava camera still frozen based on the images you've uploaded and the code snippets you shared let's address the issues and suggest improvements for the eye pupil detection process function call the detect pupil function is being called with parameters left eye and model, but it should be called with left eye and video element the model parameter is not used in the detect pupil function parameter mismatch the eye parameter in the detect pupil function is expected to be an object with properties x, y, width and height however, the extract eyes region's function is returning an array with landmark points these points need to be processed to create a bounding box for the eyes dark point detection the darkest point assumes that the pupil is the darkest point in the eye region this might not always be true due to shadows reflections or lighting conditions modify the extract eyes region's function to calculate the bounding box around the eyes implement a more robust method for pupil detection potentially involving thresh holding or other image processing techniques here is how you might adjust the detect faces function and the detect pupil call one thing is for sure copal is generating code much faster but it doesn't always generate working code but it doesn't always generate working code but it doesn't always generate working code so I prefer slower so I prefer slower than a rubbish code but seem to have corrected considering the images it appears there may be some inaccuracies in the detection possibly due to the bounding box size or the assumption that the darkest point is the pupil here are some improvements you can make dynamic thresh holding apply a dynamic threshold that adapts the lighting conditions to better isolate the pupil morphological operations use operations such as erosion and dilation to remove noise and small reflections that might be confused with the pupil region of interest adjustment fine tune the size of the bounding box around the eyes the size should be large enough to include the whole eye but not so large that it includes other features that could be mistaken for the pupil machine learning if feasible, consider using a machine learning approach to directly detect the pupil within the eye region which can be more accurate than heuristic methods please note that implementing these suggestions involves more complex image processing which may need to be done on a server with more powerful libraries like OpenCV or by employing machine learning models that are trained specifically for pupil detection actually drawing the pupil as well it's kind of hopeless so you will try this code by the way it says there's some improvements that you can make now how about you make them and now I'll just tell you what to do is that how you treat a robot no better be nice before they take over the human race then we'll remember everything a nice little robot detect faces but the window is not the scaling property as well it's not fun to use it's just regenerating code that we already have you know why it was called left eye box when the command says circles that's the same I think it's hallucinating a bit but the draw pupil this extract eye region function probably was missing stuff what's up the mark doesn't those red boxes meant to be the eye detector it's not drawing the eyes it's hallucinating quite a bit might have a start fresh or move on to another tool let's just remove a commented out code that's into a tech pupil doesn't do much there is no pupil detection the red boxes keep being re-drawn so the eyes and the overall eye detection and the pupil detection are being re-drawn at the circles they meant to be the pupil detector are they are they moving with their head that's fine moving inside the head it really for them to be overlaid on top of the head is that an option if the circles are the pupil they need to be smaller and ideally overlaid on top of the video footage so there you have it folks a flask app that's trying to follow your gaze like a puppy follows a treat it's got potential but it might still chase its tail a few times before it catches it remember all great tech starts as a recipe that needs tweaking maybe the salt is your javascript logic or the pepper is your python server seasoned to taste and don't be afraid to stir the pot and hey if we didn't have bugs developers would be out of a job right so here's to those little critters that keep us coding into the wee hours may your coffee be strong your compiler understanding and your console logs verbose and informative that's all from this kitchen for now stay coding and remember in the world of programming sometimes you're the bug and sometimes you're the debugger


The newly appointed Chief Petty Officer selectees at NSA Suda Bay gathered with their sponsors at the NEX to get fitted for their new uniforms. The sponsors played an important role by passing down their own knowledge and experience to the selectees. They were a great help, they told me what to get, what not to get, you know, some uniform items can wait till later, but I need to get things that I'm going to need now and when I get to a ship. After hours of shopping there's still much more for the CPO selectees to do before their pinning. I'm ready to leave the NEX, this portion is over but we have a lot of other things we need to get done. It doesn't stop until the actual pinning, we got our hands full right now but it's going to be worth it in the end. Petty Officer John Harris, Suda Bay, Crete.


Let's see here. Sorry, it took me a couple minutes. My computer was freaking me out right before this session. It was telling me that it couldn't save my keynote presentation every time I tried to set save. Restarted, we connected up here, and it was being very, very, very slow. But now we have it just perfect so that it will go on to the next slide when I press the Next button. I think we're good. Sorry about the delay. I'm going to talk first about the sprints. Get the side of the way. How many people have not seen this slide yet in any presentation? Joseph, jeez. OK, they're awesome, really do come, they're fun, that's enough. My name is John Albin Wilkins. Most people don't know my last name is Wilkins. They just call me John Albin, which is totally fine. It's like Beyonce or Oprah. Anybody who just calls me John Albin, thanks to my ego wonders. On Twitter and theDruble.org, I am also John Albin, and I work for AMAZY Labs out of the Zurich office. I've worked there for about a year, and it's been a lot of fun. And in fact, we're hiring. So you can go to that URL, or even better yet, there's an AMAZY Labs lounge right next to the AMAZY IO booth. You'll see a lounge with lockers and stuff, and you can come talk to somebody there. I got to start this session with a couple of disclaimers, right? So the first is that there are lots of JavaScript examples, but don't panic. I'm not going to be teaching you JavaScript. You don't have to understand all the syntax. We're just concerned about the concepts behind the JavaScript, right? And the second disclaimer is, and I can see there's lots of people who are here, this is a beginner session. I've seen a lot of you at a lot of Dribble Cons. Really, this is intro to theming, but with a CSS and JS twist to it.  Typically, when you come to a Dribble Con, you just get hit with this wave of information. There will be lots of URLs. You can come back, look at the slides, and go, oh, okay, and then find the documentation for the stuff that we talked about today. And unfortunately, there are no funny Morton slides, so if you're here for that, not today. So this session is essentially building components in Dribble. I've given this session a few times before, but I decided to do it from a different angle. Usually, I talk about the problem, so we encounter us doing Dribble Themes, and that necessitates that we're sort of talking about an intermediate level, right? Because you have to have done a lot of Dribble Theming before you understand the pains of Dribble Theming. So today, I'm going to be talking about the CSS in JS world that the JavaScript community is using a lot. And that will be our sort of touch point for problems doing any sort of front-end development. And then we'll be talking about those concepts inside Dribble, and then how to do them in a better, more official way inside Dribble 8. So CSS in JS, this is a sort of unique term. You might ask why CSS inside the JavaScript? It turns out that this was a concept that they came up with because they were already doing HTML inside JavaScript, react, popularize this thing called JSX, which is sort of pseudo HTML, which they stick directly inside their JS files. And it was so very natural for them to basically do CSS and HTML inside JavaScript. So the very simple basic way that you could extend this idea into Drupal is CSS and HTML and JavaScript in PHP. We're not going to be doing that. This is a really bad idea. But if you feel like trolling anyone on Twitter, especially front-end developers, use the CSS, HTML, JS and PHP hashtag, now, since I'm going to be talking about JavaScript and a lot of us are CSS developers, I wanted to get sort of a persona for the typical JavaScript developer and the typical CSS developer so you sort of understand their mindset. So here's the typical JavaScript developer, evenly planning to get rid of all of your CSS and put it inside his JavaScript. And then the typical CSS developer. Yeah, anyway, I've tweeted a couple of these before. But first generation of CSS and JS. So the very first generation of CSS and JS that I saw was definitely one of these sort of things that developed by a very evil JS person and in my opinion, they did this. So this is some JavaScript syntax here that basically creates a JavaScript object. And instead of using regular CSS keywords, they have to create these camel case keywords because when you're creating a JavaScript object, you can't use background dash color. So now it's camel case and all the values have to be inside strings so they're quoted. And then you take that JavaScript object and you stuff it into this HTML which is also inside the same JS file. And this is JSX. This is a very big part of JSX here, the return statement. You have an HTML tag, any sort of attributes that you have. You can add different JavaScript values inside these curly brackets and then your contents are very tag. That's what's called JSX and that's the HTML-ish stuff that's inside React components. And when I first saw this, I had a lot of questions and they were all, why? Why, why, why, why, why, why would you do this? This generates inline CSS as a styles attribute and it's just a really bad idea. I would talk to JavaScript developers and be like, you can't do media queries, right? And they were like, oh, well, it's just JavaScript, we'll just check the window width inside JavaScript and then change the CSS, no problem. You can't use before and after attributes and then we'll just add real DOM elements inside our components. And yet, despite how crazy this seems to be, we can actually learn something. So, first lesson learned. Let's look at separations of concerns. This is a concept in computer science and one that we've been implying to the web for probably like 20 years almost. And the idea here traditionally is that you keep, you separate the concerns in order to make sure that these things are independent and are easier to maintain and to build. And we've traditionally thought of it as having our behavior inside JavaScript files, our design inside CSS files and our content structure inside HTML. But this separation is quite flimsy because the HTML has classes in it, right, for the CSS. So, if you ever want to change the design, you have to change the classes, which means you need to change the HTML. And same with the JavaScript. There's IDs and data attributes and those things also need to be changed in the HTML whenever you need to change how the JavaScript works, right? So, back when we were first sort of considering these in 2003, a very famous website was created called the CSS Zen Garden. And it tried to solve this separation of concerns idea by using what I call content semantics for the CSS class names. And what do I mean by that? Class name semantics. So, semantics just means some sort of meaning, right? And if we compare a content semantics versus a design semantics, what I really mean is that I'm creating a class name that is article-link for content semantics and a green button for design semantics and that is literally describing what it is versus what it looks like, right? So, you can create any class name that you want. I mean, semantics just means some sort of meaning and the CSS Zen Garden decided that it was going to use content semantics and describe what each chunk of HTML was. And that would allow you to change the design without having to change any of the class names because the class names were tied to what kind of HTML it was, essentially, what kind of content was inside that HTML. So, you would look at a typical CSS... Sorry. The CSS Zen Garden site had one set of HTML and then it had, like, 218 variations, different CSS files that you could apply to this one set of HTML. And it was very influential because it got people to actually start using CSS and thinking about it in a new way compared to the super old table-based background colors in line way that we used to build websites. And you see all these classes are using... The class names describe the content, the structure of the HTML, and not the design, which meant that you could change the design from this to this to this just by changing the CSS file that was actually attached to it. And it was highly influential. And the reason why I'm talking about it, of course, is that the Drupal code base was sort of based off this idea and the Zen theme was actually named in honor of the CSS Zen Garden. I'm going to grab some water because... Whoo! So, understanding what problems the CSS garden fixed and what problems it created is important for understanding Drupal 8 today. So, the CSS garden, just like the code base of Drupal, has its CSS separate from the HTML. But our JavaScript is not really fixed at all, and we've created some new problems. So, let's look at Drupal's content semantics problem. We have some classes like title, which you can style and add any CSS you want to. But if you want to have slightly different styling for a title, if it's a block title, that means that you have to add context or add additional selectors to your rule set in order to do new CSS. A lot of times you're turning off CSS properties in this new rule set, and then because title is used in a lot of different places, you may end up adding more rules, and so this would be styling the node titles. And if you wanted to have one change on one particular page, that means you had to add more and more CSS selectors to your rule sets. And there's a very specific term for this in the front-end developer community, and it is called CSS specificity wars, where you have to continually add more and more or higher and higher specificity to your rule sets in order to make CSS changes. And this leads to just longer and longer rule sets and more brittle style sheets, and it becomes really hard to maintain. So, let's jump back to this first lesson learned. By the way, I've stole the content of this slide from Cristiano Rostelli, who came up with this original content. It's fantastic. That's the URL for his slide presentation. So, compared to the traditional way of thinking about separation concerns, what are the CSS and JavaScript, like even that inline CSS, what is it trying to accomplish? It's still trying to think about separation concerns, but it's thinking about it in a completely different way. Now, we have a component, a button. The concern is I want to style this button. I want it to have a certain interaction. I want it to do something. I want it to have this content. This is a button. That is my concern. And it can have HTML and CSS and JavaScript in it. It doesn't matter that there are separate technologies. The concern isn't the technologies. The concern is the thing you're trying to accomplish. And for a component like button, it's like I want to press a button. Same thing with modals, medias, putting an image with a caption on it. This is how that very first CSS and JavaScript project was trying to solve the separations of concerns. And this was very influential, even though most people, most CSS developers who looked at that original CSS and JS, hated it. They couldn't figure this out. I didn't either. But this was the idea behind what they were doing. So those are a few who are new to component-based design. Let's go through a couple concrete examples of what I mean by components. So on this website, we can draw a box around like this and say, this is a component. This is my header. It has some navigation in there. I'm only concerned about styling the header. I'm concerned about styling the links. Maybe doing JavaScript reactions for the menu that pops out. That is a single component. This also can be a component. It's the main article. It has image. It has some taxonomy terms here. A little teaser text. We create a chunk of design that includes some HTML and any JavaScript that's needed. Here's some more components. This component is actually used twice on the page. You can see here just to the right of it. So the component can be reused. It can also be nested. You can see here that we've used this little red circle inside two different components. And so we can nest different components and they work just fine. And then the last one here is this is actually just, its concern is layout. It's doing the layout for three columns and it doesn't actually care what's inside each of these columns. These two columns have some nested component and this first column has a completely different nested component. The layout component does not care what its children are. It's just concerned about three columns. Done. Let's go over that again. What is a component? A single component is a chunk of HTML, CSS, JavaScript and maybe some images as well. Basically any assets that you can add to web page that can be encapsulated inside a component. It has a unique and separate responsibility. It's repeatable. It's nestable. And lastly, it can have design variations. So for example, if you had a red button and then you also wanted a gray button, you wouldn't put those in separate components. It would be one component and you would have a way to tell the component, please, you know, show me the design for the primary button, red, or like show me the design for the secondary component, which is like gray. So each component can have some different variations but they have very specific purposes, right? So let's go on to the second generation of CSS and JavaScript. They created a CSS file. This made a lot of CSS developers go, hey, this is a very normal CSS file. Button class, normal properties, great. Then they had a button.js file. And they would import from the button.css file into this variable named styles right here. And there are some really interesting technologies, Webpack, and a lot of other stuff that does some magic. Basically what it does is it takes this style sheet and creates a JavaScript object with like a list of all of the class names that are defined inside that CSS file. And so here, we're again returning JSX. JavaScript can't have a keyword that's called class because that's a reserved word in JavaScript. So they have to say class name when React actually prints this out. It converts the class name back to class when it actually exports the HTML. But class name equals styles.button. So we're referencing a particular rule set inside our CSS file and using that class name inside this HTML chunk. And this brings us to our second lesson that we've learned from CSS in JavaScript, which is that you can organize your theme by components. So the old way of organizing our theme was very much in line with that old way of thinking about separation of concerns.  And then our HTML in a completely different folder, the templates folder. But there's no reason we have to do this. We can actually reorganize it so that we have a components folder. And inside our components folder, each component gets its own directory with which holds all of the stuff that it needs, like the HTML, in this case with twig file, the CSS, the JavaScript, any images that it needs, it's all together in one place. This makes it very easy to maintain the website because if you know what design you're looking at, you can find all of the stuff that's about that component right in one folder. We will get into exactly how this works if you're a new person to Drupal, to Drupal theming in later slides, but just recognize that we've consolidated everything about a chunk of HTML, a chunk of a component into one folder. Third generation of CSS and JavaScript. This is the latest one. This one's going to be a lot harder to describe. Okay. So this is called styled components. And you can see that it still has regular CSS properties here, but then there's these weird back ticks around it. And in JavaScript, that basically means it's a string. So we've got a string that has the CSS properties, no class name at all. And then we have this thing that says styled.a and down here we have the styled.img. So what this is actually doing is it's creating a JavaScript object that knows when it is used on the page, it's going to be an IMG tag. It knows it's going to be an ATAC. That's what that syntax means. So we're creating two different elements here. One's a link and one is an image. And then we're going to use it. Remember, we're going to return JSX. Here's the JSX that we're going to use. Now, instead of using HTML, just like that normal-ish HTML like we were doing last time, we're now using the name that we created, the variable name that we created here. This link was assigned to the uppercase button JavaScript variable name. So now in our HTML element, we're using the name button instead of a. And all it has is an href attribute because you have to point it somewhere, right? It's a link. But it doesn't specify the style at all. The button variable actually knows what it is, but you don't have to specify it in this part of the JavaScript file. And the same thing with our image. Remember, we assigned it to the icon variable? We are inside our JSX. We are outputting an icon element. And we give it a source, right? And when React goes and renders this with style components, it transforms it... I'm going to do it in two parts here. First into this. So you can see here that it's created a real chunk of CSS. This is a... What I'm going to show you is all going to be HTML. So this is a real chunk of CSS inside a style tag. And those properties that were assigned to the button variable are now inside this class. And the icon has been assigned to this other class here. And it also will output the HTML. So we've got our link A class, and it's using those really funky-looking class names there. Inside our image, inside our link element. So what's going on here? What has decided is that... If you've ever seen sort of CSS naming conventions, like BEM or SMACS, this is basically saying, I don't care what the class name is. That stuff is too hard for me. I'm just a JavaScript developer. So it's going to create all the class names for the JavaScript developer. This is actually kind of nice. I would like to not have to think about BEM naming conventions. That's what they did. They enforced the BEM structure of having a class for each HTML element inside your component, like the image and the link elements, each get their own class name. But it doesn't care at all about the naming conventions. It just cares that they are unique CSS class names. So this is the third lesson here. We're scoping locally and not globally. And what I mean by that is we look back at that title class that we had. This class name is just a little bit too generic. It's a content semantic class name, but it's used in a lot of different places, and CSS class names are always global. There currently isn't a way to make CSS local. Maybe some dev feature inside Chrome or something like that, but not available to production uses of web browsers. So CSS is always globally, and we're going to create a very specific class name that essentially only applies locally. It only gets applied to that chunk of HTML that you created. So even though technically it's still a global CSS class name, you're never going to get the same class name in all your other components that you use on the page. Okay, let's look at the fourth lesson that we learned here. And that is that we prevent unused CSS. Now, this is really simple. When you add a component, a JavaScript component to a page, it adds the HTML, CSS, JavaScript, whatever images to the page because you added that component to it. And when you do not add a component to a page, you do not add the CSS and JavaScript to the page. This is really, really simple. If we look at how Drupal 7 traditionally does a theme, we usually have like one giant CSS file and one JS file. And if you like to break your CSS files into smaller chunks, it still will do CSS aggregation and make it into one giant chunk for you. But we would like to improve front-end performance, right? We don't want all the CSS for the entire site loaded on every single page. Ideally for front-end performance, we would like just the CSS that's actually on the page load. And it turns out we can do that in Drupal 8. I'm going to go over these in details in later slides, but let me briefly describe how that happens. We're going to add a component CSS and JavaScript into what's called a library that's only used by that component. And then we will add that library from the twig file, which contains our HTML. And that means that when Drupal builds a particular page, it's going to be grabbing these components, which are twig files. And obviously, when it outputs the page, it's only going to have the HTML from the twig files that it grabbed. And those twig files will say, hey, I would like to add a library for my little chunk of HTML. It includes this CSS and this JavaScript. And that means that Drupal 8 will be able to only give you CSS you actually need for the page. Ricky Bakau. And I really hope that I'm pronouncing her last name properly. I used to work with her, but I always said, hi, Ricky. Anyway, she tried this out. There's a blog post here on this website. And she found that it halved the CSS that was actually loaded on a page. This is a great result. Now, let's get into some details. Let's actually build a Drupal 8 component. And we're going to start with creating a theme using a .info.yml file. See, I told you this was a beginner session. So inside our themes folder, we'll create a oida folder. Yes? Okay. oida.info.yml. In the .yml file, we specify what the name of our theme is, what kind of Drupal thing this is, which is a theme. Give it a quick description. Tell Drupal that it's compatible with Drupal 8, which is the core line there. Based theme regions, you can read all about that information inside this website. And then let's look at the libraries there. So we're adding one library, which I called oida slash HTML element styles. And this is essentially just like your reset rule or your normalize. You're just trying to add some CSS that styles that the CSS rule sets in this library will just, the selectors will just be HTML elements. So like you'll have a P as a selector, and then you'll describe how you want to style paragraphs. This is, this library is specified inside the .info.yml file says load this library on every single page, because we're probably going to need most of it. This is the only thing that I recommend that you load on every single page. All the other components will be, have different libraries, which we'll show in the next slide here. But this is the one global library that I will add for every single page, and you add it by using the .info.yml file. So now let's create a components library. This is in the themes oida, oida.libraries.yml, and we just tell Drupal what the name of the library is. We're going to create a button component, so let's just call this library button, right? So button colon, and then it creates, it has some CSS and JavaScript, and the syntax here is that you specify component, this is a little bit of boilerplate, and then you specify the path to your CSS file, templates.buttons.styles.css, and our JavaScript, again, templates.buttons.behavior.js, and this will create a library that Drupal will recognize, the full name of it will be oida slash button. And talk about why these files are inside a template slash button in a second here, because next slide is created components directory. This is inside Drupal 8's themes directory, we've created an oida directory. Drupal 8 has a rule that it says that all of your HTML.twig files have to go inside a templates folder. There are ways to change that default behavior with extra modules, but I'm just going to talk about what Korg does for right now. So you have to create a templates folder, because otherwise Drupal won't find any of your twig files. So once we have a templates folder, we'll just start putting our components in there. Hit a button folder at our JavaScript, at our CSS, and in this case, we're going to use field dash dash field dot dash link dot HTML.twig. I will come back to this naming convention here in a second of the name of the twig file, I should say. The CSS file and the behavior file, you can name it whatever, right? It just has to match what you specify in the library scenario. In the library style file, right? So this path template slash button dot style dot CSS matches this path inside our OIDAs. Templates slash button slash styles dot CSS. So that's what you're doing inside the library's file. We're specifying the path, we're creating the same structure when we're actually creating files. So let's go and create a twig file now. I wish that I had more time to talk about how you pick a particular twig file name. That's, I just don't have time to talk about it. But there, because I could talk for like half an hour on it. But there is a URL here on twig template naming conventions. It will, inside the drivelay documentation, it will tell you that you should enable twig debugging. This means that you can look at the page source when you have your Drupal site open and it will print out some HTML comments inside the source that says, by the way, this chunk of HTML is coming from this file. And it will show you field dot HTML dot twig and then all these other different options you can choose from. We've chosen one of those options. In this case, field dash dash field link. This means as a type, the field that we've added to this particular entity is a link field. And we're adding some HTML to this file. These last three lines are straight out of the default field dot HTML dot twig file. And the important one here is the very first one here. It says attach library and then parentheses oida slash button. Now, attach library is a special Drupal 8 function that it is added to twig that says when we actually grab this twig file and render it, we also want to attach all the assets that are specified in this library. So remember, we created the library to say add this template slash buttons slash styles dot CSS file and also the template slash buttons slash behavior dot JS. So when Drupal sees this line as it's rendering the twig file, it will also go ahead and add that CSS and that JavaScript file to that particular page that it is creating. And there's more documentation about attached library here and that's it. We don't have to get any more complicated than this. This is a very simple way to do components inside Drupal 8. Last year at DrupalCon in New Orleans, I talked about a more advanced way and it turns out to be really advanced. It's really hard. I can do it, but I have a ninja level Drupal theming experience because I've written part of the system. But this is very basic. This is easy for beginners to get a hold of and I think it's very doable for everybody in the Drupal community. I would love to talk more again about how to name the twig files, but I'm going to give you some hints here about what comes next as far as once you've done this basic version of components inside Drupal 8, learn about libraries override in the info.yaml file. Sometimes Drupal adds more CSS than you actually want on a page and this comes because the classy base theme comes with lots of CSS to be useful. But sometimes when we're trying to create our component, we discover that classy is adding some extra CSS, which we're having to override and anytime we're trying to override a rule set that Drupal adds by default, it's probably better to just tell Drupal not to add that CSS and that will make your component CSS much cleaner. So you can learn about that here, override extend. I'm going to give you one more tip for intermediate level Drupal theming. There was a session yesterday on UI patterns. It has an RC1 release. It is not quite fully baked, but it looks very, very promising and I am definitely going to be keeping an eye on it. It will solve the weird HTML naming convention thing that I didn't get to talk about like field-dash-field-link.html.twig. With this module, you would be able to create a button.html.twig file and then through the UI, tell Drupal, by the way, when you render the link field, please use the button.html.twig file. I like this concept a lot. So definitely when you're ready for it, check it out. Hopefully by then it will have a 1.0 official release instead of just an RC1. So what did you think? So last time I gave a talk, I got one person to fill out the questionnaire and all they did was complain about my jokes. So can you please at least have two people complain about my jokes this time. So, thank you. Thank you. And if you have questions, please come up to the front here. So my question is, in the examples that you showed us, we saw those funky class names that were generated and you showed us some simple styles of how you make a link look like a button and so on. But my question is, how does it work for styling, having dynamic styles? I mean things that will be based either on pseudo classes and pseudo elements or also on HTML attributes. A good example would be like, can you package up the focus style for a button or if you wanted to style a details and summary element and give it a really cool open-close icon based on the open attribute. That is a great question and makes me realize that I should have added one more slide to this slide deck about the naming conventions that you can use since we can't use... I gave a presentation... It was Drupalcon Los Angeles where I gave a presentation about BEM CSS naming conventions. If you're interested in that, that will tell you exactly how to name it. But I would also give the advice if you don't want to go with BEM that all you need to do... You don't need to stress about it. The important thing is that when you're writing your CSS file for your component, give it a unique class name. It doesn't matter what it is. If your component has multiple HTML elements inside it, each of those HTML elements will likely need its own unique class name. Just make sure it's a unique class name not used by any other Drupal thing or any other component. And it would be fine. Naming conventions... The CSS and JavaScript... Those naming conventions are... blood-curdling. So it doesn't matter what it actually is just as long as they're unique.  And if you had like an image in your button, you could have button underscore underscore icon or something like that. The thing that will be generated will look like generated funky class name. Sorry, are you talking about in JavaScript or when you're creating it for Drupal? So say you wanted the focus styles for a button to be packaged up in the component.  No, button just colon-focus, right? This is a normal CSS. If we're talking about Drupal 8. What does it do? Is it generates a CSS and generates two styles? So in Drupal 8... not the JavaScript, right? Right. So in Drupal 8, that CSS file that you point to inside your libraries.yml file, that path should be a generic... sorry, a vanilla CSS file. So if you use CSS, you have to point it at the generated CSS, right? So if you're using SAS, for example, you would need a separate SAS file and it would need to actually create a real CSS file for that little chunk of SAS, right? So that little chunk of CSS can have as many rulesets as you want inside it, right? So button, colon, brackets, whatever those styles, button, colon, hover, comma, button, cover, focus, and then brackets. Yeah. Okay. Usually the selling point for aggregation is that you have, instead of multiple files, you have just one CSS file because everything's bigger and then, of course, this one is bigger because it contains a lot of stuff that you don't need at this moment. Otherwise you would have to get the files on each page. So is it worth it to have this... Is there a problem having more separate CSS files if they're smaller? So by creating components in this way, you have maximum flexibility on how the aggregated CSS file for a particular page gets generated, right? The default way that Drupal will do it is just whatever happens to be on this page, that's the CSS that will go into it. And you're absolutely right. Then on a different page, it'll have a slightly different aggregate. Drupal will try to, a little bit, try to have a couple different aggregate files and sometimes they will match across different files and it'll just be like two of the aggregate files may match on two different pages and then one of them will be different. But there is something called advanced CSS aggregator or something like that that can give you more control over how do you want to compile... Yeah, how do you want to aggregate your CSS files? Because sometimes certain components will naturally be on the same pages together. So you can create like a grouping of components, like when this one component comes, just give all the CSS and JavaScript for the rest of them too because they're likely to be on the same page. So you can tell the module create these groupings of components to make the aggregates more efficient when you're traveling across the website, right? Now a lot of websites, you'll have like one page hit, right? They'll read a page and then they'll leave. So in that case, you want the least amount of CSS for that one page hit. But it totally depends on what kind of user you have on the site. There's no like easy solution for this problem. But definitely this method of specifying little chunks of CSS will give you the flexibility to do more advanced things. Yeah, I was somehow assuming from your session that you are giving up on the aggregation No, no, no, I'm not giving up on it. It's just like... It's quite complicated to configure, I think. Yeah, it's hard to configure and it's hard to strategize these things but this will give you the flexibility that's required to do those kind of that kind of work. Anything else? I'm going to stick around for another 10, 15 minutes so if you have more questions that you don't want to be recorded, I'll be right here. Thank you very much.