Reading Reflection #4

Don Norman presents a key idea in “The Design of Everyday Things,” which is feedback in design. According to Norman, feedback is a means of informing the user of the outcomes of an action. He uses commonplace examples to demonstrate this, such as sitting at a traffic light without seeing any indication that the system has spotted your automobile, or pushing buttons on an elevator without knowing if the elevator is on its way. This idea emphasizes how crucial it is to provide users with prompt, understandable feedback so they may be assured that their action has been recorded and is being handled. Ineffective feedback can cause consumers to feel doubtful, angry, or confused, which can make them dislike the system or product.

When I think about it, this idea has really changed the way I think about user interface and design. I can think of several instances where I kept pressing buttons on gadgets or user interfaces and got no reaction. I’ve always found this experience disconcerting because I’m not sure if my activities were acknowledged. I completely agree with Norman’s assessment on the importance of receiving feedback that is both clear and fast. It draws attention to a prevalent problem found in many designs and emphasizes how crucial it is to include transparent feedback methods in order to increase usability and user happiness. This understanding highlights the vital role feedback plays in enabling successful human-machine interactions, and it motivates me to examine designs more closely, both those I work with on a daily basis and those I might develop.

Asciilumination – Assignment 4 – Dachi Tarughishvili

Passing by Interactive Media Lab, I always noticed those TVs that used webcams to track our movement and demonstrate interesting visualization using predefined symbols. I always wondered how it actually worked. So for this data visulization assignment I wanted to recreate it and perhaps add some more adjustments. I followed Coding Train’s coding challenge tutorial regarding ASCII Text images where most of my code comes from.
The basic mechanism behind this program is to map the pixel brightness values which are calculated by dividing their average RGB values and mapping it to characters from density character strings. In this case, I am using ‘ÑYUAD876543210?!abc;:+=-,._’; since initial symbols take up more density and show contrast better but it can realistically be anything. Super bright parts of the image have no space value at all. Additionally, there is no Canvas, and this is direct html implementation with little bit of CSS. I also added a slider for density value which adjusts number of spaces that are added to the string, which acts similiar to how contrast slider would act in photo editing app. If uyou think about it, thats actually whats happening. There are more spaces for wider value of brighter pixels. There is also a Toggle Color button on top left, which assigns the symbols colors based on initial pixel value. This is done per frame basis.
To ensure that you see full working project, make sure to follow P5 link, since this website does not correctly display it and also you need camera permissions anyway since it takes the video of your webcam.
Here is perhaps the most important code out of entire project:

 //loop to iterate over pixels
  for (let j = 0; j < video.height; j++) { //iterates over rows (height)
    for (let i = 0; i < video.width; i++) { //iterates over columns (width)
      const pixelIndex = (i + j * video.width) * 4; 
      //calculates index of pixel in videos pixel array based on its x and y cordinates (i and j). basically vertical and horizontal displacement. Video width indicates how many pixels are in each row. r, g b, a so we multiply by 4 since pixel takes up 4 spaces in array
      const r = video.pixels[pixelIndex];
      const g = video.pixels[pixelIndex + 1];
      const b = video.pixels[pixelIndex + 2];
      const avg = (r + g + b) / 3;
      const len = adjustedDensity.length;//to later map brightness value
      
      const charIndex = floor(map(avg, 0, 255, 0, len)); 
      
      //maps avg value from 0 to 255 to 0 to len. floor is used for rounding
      
      const c = adjustedDensity.charAt(charIndex);
      
      //brighter pixel = higher char index lower density
      
      const charColor = `rgb(${r},${g},${b})`; 
      //its a template literal, javascript uses it for embedding expressions within the string
      
      if (c == " ") {
        asciiImage += "&nbsp;";
      } else if (check == true) {
         asciiImage += `<span style="color:${charColor};">${c}</span>`; 
      } else {
        asciiImage += c; //adds c to our image
      }
      
      //span element is inline container in hztml used ot apply styles without line break
      //if our c is empty by mapping, correspond that to true space (html does not conventionally display empty spaces) 
      
    }
    asciiImage += '<br/>'; //line break to start fresh rows
  }
  asciiDiv.html(asciiImage); //sets html content of ascidiv to our finalized asciimage, by continously drawing we update div content and thus motion is live
}

The code is fully commented but the general idea is to find out r g b values for individual pixels. After that, we find average value which corresponds to our brightness. We map our string index to brightness values. Therefore we have a constant C which is a character for every-frame and we add it to our frame. If color is on, then its color is modified.

In the future, I could work on optimizing since. Refreshing html elements so many times, especially when color is applied is very taxing on CPU and the process becomes laggy. Lowering frame-rate does not help much. Additionally, I could add more adjustmenets and variables, such as video size, font options and more. The latter is especially interesting since the font I am using has same horizontal length. Variable font would be harder to implement. Overall I am very glad with how this project turned out and would like to work on it more in the future.

Week 4 – Reading Response: Every day’s Life Design | Haziel

I found the reading really interesting and relatable as it provides a thought-provoking exploration of design principles and their application to everyday life, particularly focusing on the challenges posed by modern design complexity. Don Norman’s concept of “Norman Doors” highlights a common frustration experienced by many individuals, including me, when interacting with poorly designed products, such as doors with ambiguous instructions.

The reading also made me think of other trivial daily life examples. For instance, the design of a smartphone interfaces often reflects the principles discussed in the reading, particularly regarding feedback and conceptual models. When typing a message on the smartphone keyboard, the visual feedback of each keystroke appearing on the screen provides immediate confirmation of input, enhancing the user’s understanding of their actions. This feedback loop is crucial for users to feel confident and engaged with the device.

Assignment 4 – Lyrics Video | Haziel

For this assignment, I got inspiration from one of my favorite Brazilian songs, Wave by Antonio Carlos Jobim. The objective of this project is to display a Canva that looks like a YouTube lyrics video. Using generative text, I have created a CSV file with the translation of the lyrics. Then, it is loaded in the main sketch along with the background image and the instrumental of the song.

Rather than just displaying the lyrics on the screen, I added a bit of interactivity as the user gets to choose when to read the next sentences. So, if we click on the screen, we load one sentence at a time, following the order of the song. Additionally, I added some animation to the sentences, as they move in a wave format to match the concept of the song. It also allows the user to immerse themselves in the project and read the (I would say) beautiful and romantic lyrics.

When coding this assignment, I also got references from the text() function.

function draw() {
  // Display the background image
  image(bgImage, 0, 0, width, height);

  // Sets the text alignment to center
  textAlign(CENTER);
  
  // Calculate y-coordinate with a sinusoidal function for wave animation
  let y = height - 20 + sin(frameCount * 0.05) * 10; // Adjust the amplitude (10) for desired wave height
                                                     // Adjust the frequency (0.05) for wave speed

  // Draw the current sentence at the bottom center with animated wave effect
  drawWords(width / 2, y);
}

function drawWords(x, y) {
  // Text color
  fill('gold');

  // Display the current sentence at the specified position on the canvas
  text(sentences[currentSentenceIndex], x, y);
}

Reflection: One area I could still improve is to make the Canva more animated and dynamic. Currently, the animation is limited to the wave effect applied to the text as it moves on the screen. However, there are several ways we can enhance the animation to make the canvas more engaging, such as background animations and transitions between the sentences.

Assignment 4 – Reading Reflection

The excerpt from Don Norman’s “The Design of Everyday Things” offers a perceptive look at the psychology of commonplace objects and their designs. In his discussion of frequent problems with doors, light switches, and technology, Norman highlights the significance of design features like affordances and signifiers. He contends that effective design should be intuitive, enabling people to utilize a product without the need for manuals, mostly by means of obvious and sensible hints included into the design itself.

When I think about it, Norman’s emphasis on user-friendly design resonates even more. From my own experience, I have come across a lot of non-intuitive products and interfaces, which has caused annoyance and mistakes. I’m more conscious of the importance of user-centered design now that I’ve read this, and it’s inspired me to think about how the systems and items around me may be made clearer and easier to use. Norman’s concept of “affordances,” which refers to the potential interactions between people and their surroundings, has altered my understanding of how products should be made to fit naturally with human use rather than requiring users to adjust to complicated or counterintuitive systems.

Week 4 Readings – Norman Doors

Ah yes, should I pull or should I push this door? From the image, we can already tell that something is off with the door. The sign says to pull the door, yet the handle is flat. These doors are commonly referred to as Norman Doors, introduced by Donald A. Norman in his book we read this week.

When designing something, it is always best to remember the target audience. Most object designs require human senses as an input to be used. While this does sound able-ist, we should also ask ourselves the question: How would this object be used for those who require more assistance? 

People will always seek the path of least resistance. An intuitive design is always good. We can measure how good a design is by simply using our senses. If it feels ‘natural’ to use, as if it is part of our body, it means the object is well designed. Otherwise, if we stop to think about how to use the object, that means it is redundant.

I believe that the concept of affordances Norman wants us to embed in our minds is this: As a designer, we need to put ourselves in the shoes of the audience. Designers can impact the lives of its users, be it for good, or for the worse. Being able to distinguish the holes or problems in the experience of our design is an important aspect to always remember.

Assignment 4 – UI/UX Reading

“Design of Everyday Things” presents a compelling exploration of the interdisciplinary nature of design and the challenges involved in creating successful products. For me, it emphasized the importance of considering various perspectives, goals, and priorities from different disciplines, such as marketing, engineering, manufacturing, and customer support. In the modern age, where industries increasingly rely on cross-functional collaboration to innovate and deliver products that meet diverse consumer needs, the point that the text makes shine. In today’s fast-paced market, where competition is fierce, understanding and integrating these varied viewpoints is crucial for achieving market success.
Don Norman highlights the significance of user experience and the formation of conceptual models in product design. He underscores the gap that often exists between the designer’s vision and the user’s perception, emphasizing the critical role of the system image in bridging this divide. In our modern digital landscape, where user-centered design principles are paramount, this notion holds particular relevance.
Norman stated many things which I found relevant to myself. One such idea was that designers will often take shortcuts when something is too complex. This reminded me of myself: I am lazy, and if there is a way to do something quicker without too much of a quality sacrifice, I will do it. Interestingly, I also remembered Japanese web design, and how it differs from Western websites. While her in the West, sites are usually as streamlined as possible, Eastern sites often feel cluttered to me, and present a lot of information all at once.

Assignment 4 (production 4) Word Search

The concept of this assignment is a word search. I was inspired to do this because of how much I help my younger brother with his word search activities at home. So I immediately started working on the idea.

I started y creating a grid and then have randomized letters in the grid. There are three specific words that you need to find: “WOW” “FUN” “CAT”. Obviously there are more extra and bonus words that you will find in the grid. The process was long but this is what I ended up with. Please mouse click on the letter that you want to highlight:

A big part of the code that I am proud, which was the most challenging part is the WordGrid Class that I created to have many different functions.

class WordGrid {
  
  
  
    // Constructor 
    constructor(gridSize, cellSize) {
      // Number of cells along one edge of grid 
        this.gridSize = gridSize; 
      // Size of each cell in pixels
        this.cellSize = cellSize; 
        this.words = ['FUN', 'WOW', 'CAT']; 
      // Initialize grid layout
        this.grid = this.initGrid(); 
      // Place words in the grid
        this.placeWords(); 
      // Fill empty spaces in grid
        this.fillGrid(); 
    }

  
  
    // Initializes grid with empty values.
    initGrid() {
      // Array to hold grid data 
        let grid = []; 
      // Iterate over each row 
        for (let i = 0; i < this.gridSize; i++) { 
          // Initialize an empty row
            grid[i] = []; 
          // Iterate over each column in row
            for (let j = 0; j < this.gridSize; j++) { 
      // Set each cell to default state with no letter and not colored
                grid[i][j] = { letter: '-', colored: false };
            }
        }
        return grid; 
    }

  
  
    // Places words from 'words' array into grid 
    placeWords() {
        // Iterate over each word and its index in the array
        this.words.forEach((word, index) => {
    // Calculate row number based on word's index to space out words
            let row = index * 2; 
            // Place each letter of the word into grid.
            for (let i = 0; i < word.length; i++) {
       // Set cell at calculated row and current column to letter of word
                this.grid[row][i] = { letter: word[i], colored: false };
            }
        });
    }

  
  
    // Fills empty cells of grid with random letters
    fillGrid() {
        // Iterate over each cell in grid
        for (let i = 0; i < this.gridSize; i++) {
            for (let j = 0; j < this.gridSize; j++) {
                // Check if cell is empty (marked by '-') 
                if (this.grid[i][j].letter === '-') {
                    // Set the cell to random letter
                    this.grid[i][j].letter = this.getRandomLetter();
                }
            }
        }
    }


  
    // Returns random letter from the alphabet
    getRandomLetter() {
      // String containing all letters 
        const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
        // Return random letter from alphabet string 
        return alphabet[Math.floor(Math.random() * alphabet.length)];
    }

    // Toggles color state of specific cell
    toggleCell(row, col) {
        // Check if cell contains a valid letter (not '-')
        if (this.grid[row][col].letter !== '-') {
            // Toggle 'colored' state of cell
            this.grid[row][col].colored = !this.grid[row][col].colored;
        }
    }

  
  
    // Draws grid on screen
    draw() {
        // Iterate over each cell in grid
        for (let i = 0; i < this.gridSize; i++) {
            for (let j = 0; j < this.gridSize; j++) {
              // Set fill color based on cell's 'colored' state
                fill(this.grid[i][j].colored ? 'red' : 255);
                // Draw border around cell 
                stroke(0);
                // Draw cell as rectangle
                rect(j * this.cellSize, i * this.cellSize, this.cellSize, this.cellSize);
                // Set fill color for text (letter) to black
                fill(0);
              // Align text to center of cell and draw letter
                textAlign(CENTER, CENTER);
                text(this.grid[i][j].letter, j * this.cellSize + this.cellSize / 2, i * this.cellSize + this.cellSize / 2);
            }
        }
    }
}

initGrid(): This function creates a two-dimensional array with objects that correspond to each cell in order to set up the grid’s basic structure. At first, I had trouble seeing the grid as an arrangement of objects instead than just letters or empty spaces. But structuring every cell as an object with letter and color characteristics made managing the state of the grid more adaptable.

placeWords(): It was difficult to arrange the words on the grid, especially to make sure they matched and did not overlap. Every word in this condensed form is arranged horizontally and separated by rows. This function established the foundation for comprehending how words interact with the grid, even though the true problem lay in creating more sophisticated placement algorithms.

fillGrid(): To finish the setup of a standard word search puzzle, random letters had to be placed into the remaining vacant cells of the grid. This method iterates across the grid, substituting random letters for unassigned cells. It filled all the cells that had “-” instead of letters of the words that we placed in the grid.

getRandomLetter(): This function selects a letter at random from the alphabet. It fills in the blank cells in the grid, completing the word search problem and enabling gameplay. It’s a little but essential component of the code. It works directly with the function before it.

toggleCell(row, col): The requirement for grid interaction made this function difficult to implement. Users can choose which cells to change color by clicking them. The gameplay revolves around this interaction, which lets players highlight words they come across.

draw(): Lastly, the draw method gives the word grid a visual representation of each cell’s condition, bringing it to life. For the game to be visually appealing and functional, it was essential that every cell’s content—a letter—and state—colored or not—be shown clearly.

 

There are a couple of limitations for my assignment though. First of all the function that places the words in the grid is placing them all horizontally and under each other which makes the word search game less interesting. Moreover, I only chose three words all with three letters only which again makes this game easy and will end fast. From the technical side, you are required to press on every letter of the grid when you find a word which makes it harder and less appealing to play the game. Making it more realistic like striking through the letters when the correct word is found will make the game more realistic and more appealing to the player. However, overall, I think I did a good job with the representation of the grid and creating a separate  file for the WordGrid class to make the code more organized.

 

Assignment 4 – Saeed Lootah

Going into this project I originally had no idea what I was going to do. With the previous projects it was easy to come up with ideas but when it came to typography I didn’t know how I was going to make it aesthetic. I could have done data visualization but I couldn’t think of any data or statistics that mattered to me. In any case, the first idea that came to mind was to first try and make a bouncing ball which goes across the screen, then to make it about typography I would have said ball go to a certain point on the screen to spell out a word. It was a simple idea but as you will see down the line I added a few small details to make it more appealing.

I began first with creating the bouncing circle as you can see below

 

For some reason it has decided to fall through the bottom of the screen, but I promise when I first made it it worked fine :). In doing this simple animation I learned a lot. I had taken a lot of inspiration from my previous assignment where I wanted to make circles that went around. In that previous assignment I wanted to use vectors originally but didn’t know how to. However, after showcasing it in class my professor as well as Pi explained to me how to use the vector to add a new position. It was done by adding the vectors x or y value to the x or y value of the circle. You can see this in more detail in the code below.

update() {
    
    angleMode(DEGREES);
    
    this.posX = this.posX + this.v0.x;
    this.posY = this.posY + this.v0.y;
    
   // theres a problem where when it hits the corner it decides to go in a straight line into the next corner. Not sure why this happens, I think its to do with the if statements, but its rare enough where debugging isn't worth it (at least by my standards).
    
    // overarching if statement, if false then it goes into other if statements to see which part is false
    
    if(!(this.posY < height && this.posY > 0 && this.posX > 0 && this.posX < width)) {
      
        if(this.posX > 0 && this.posX < width) {
        // top and bottom
        if(this.posY < 0) {
          // top reflect
          print("reflect top");
          this.v0 = p5.Vector.reflect(this.v0, this.upVector);
        }

        if(this.posY > height) {
          //bottom reflect
          print("reflect bot");
          this.v0 = p5.Vector.reflect(this.v0, this.downVector);
        }
      } else {
        // left and right
        if(this.posX <= 0) {
          // left reflect
          print("reflect left");
          this.v0 = p5.Vector.reflect(this.v0, this.leftVector);
        }

        if(this.posX >= width) {
          // right reflect
          print("reflect right");
          this.v0 = p5.Vector.reflect(this.v0, this.rightVector);
        }
      }
    
    }
    
    // noise for the heading
    
    
  }

The specific line where I do the adding of the vectors x and y component is at the top. Afterwards I made a lot of if statements and created some other vectors from which the object could reflect off. The reason I did this with vectors again was because there was a method that already existed which I could use instead of doing math. By the time I had gotten all of this to work I was very happy with how it turned out. You’ll see with the bottom comment that I at one point was going to add noise to make the direction slightly random, but it didn’t work out unfortunately. I may work on this for the next assignment just as I worked on vectors for this assignment.

Then after that, I made another sketch. The plan for this other sketch was to just make the points surrounding text. Up to this point I had only ever done it once in class and that wasn’t enough for me to really understand how it works.

 

Its a very basic sketch, and that was kind of the point. It took me a while to make it and that was mainly because I was trying to center it. The way I did it was by subtracting half of the width of the text to the x position of the text since by default it’s drawn from the bottom left of the text (as far as I know, it may be top left but it doesn’t matter for centering). The problem was getting the width, for some reason textWidth() wasn’t working so I had to use the textBounds() function which is part of the font class which already comes with p5js. After all that I was finally ready to make the final project.

Also I should mention, my original plan was to make the text in arabic but I saw a stack-overflow post which said p5js isn’t great at doing right to left text and so I decided not to in order to save time.

By this point, my plan was that I would have all of these bouncing circles, one for each point in the text and then when the user holds down a button each button would return to it’s appropriate point on the text. Because I had done a lot of work before this working on separate features I was struggling with I could bring it all together and in theory it would mean that I wouldn’t have to spend as much time. I put the text sketch into a function, and since I had made the bouncing circle in a class I copied that too. In hindsight, I could have made the bouncing circle its own class to see how that would work and to learn a bit more but I, again, my try to do that for the next assignment.

Below is the finished product (press left click)

The text can be changed

Week 4 Reading Response: The Psychopathology of Everyday Things

This was a really interesting reading on the principles of good design. A lot of considerations mentioned by Don Norman seem obvious from the user standpoint but are often forgotten by product designers. Norman goes in depth regarding the principles he sees as crucial for designing good products, especially products with increasing functional complexity.

This reading is archaic. After all, the latest technologies mentioned here include new types of landline telephones. But everything mentioned here is relevant in the Web age. Even now, we still see complicated products in the market that need you to search for an instruction manual on Google. And UI/UX is a very important consideration on websites and applications. Yet many websites fail at one or more of Norman’s principles of good design: providing good conceptual models, making things visible, mapping, or feedback. A common example is the fact that a lot of websites that are mapped well on desktops completely lose all sense of mapping on mobile, even when (and sometimes especially when) using the mobile version of the website. An example from the application side of things might be Slack, whose problems range from the fact that separate channels usually do not display notifications if not actively logged into them (at least in my experience), the interface that seems hostile to new users with its multiple menus of options (some of which don’t visibly change anything), and notification “quiet hours” being turned on by default. Many of these problems have slowly been fixed by updates, yet Discord, or even WhatsApp, feels like a better alternative to Slack as a group messaging service. Which is not to say that the other two apps don’t have their own UX problems either.

To close off, the final line about the paradox of technology struck a chord with me. “Added complexity and difficulty cannot be avoided when functions are added, but with clever design, they can be minimized.” This, after all, is the very principle of UX design.