Compare Duplicate Data From a List with Inputed Data - java

I want to check duplicate IDs from a list with the data I inputted, then increment the qty variable in the list. If it's new data, it will add a new list.
This is my code
public void addBarang(Barang barang){
int id_barang = barang.getId();
if(this.list.isEmpty())
{
list.add(barang);
}
else
{
for(int i=0;i<list.size();i++)
{
if(list.get(i).getId() != id_barang)
{
list.add(barang);
System.out.println("Added");
break;
}
if(list.get(i).getId() == id_barang)
{
int new_qty = list.get(i).getQty()+barang.getQty();
list.get(i).setQty(new_qty);
}
}
}
}
Even if I input new data it always increments the qty of old data and the new data is not added (basically always end in the "else" section).
Code for inputing data
Gudang gudang1 = new Gudang(1,1);
System.out.println("ID: ");
int id = input.nextInt();
System.out.println("Jumlah: ");
int qty = input.nextInt();
System.out.println("Nama: ");
String name = input.next();
Barang barang = new Barang(id,name,qty);
gudang1.addBarang(barang);
Barang Class
public class Barang {
public static int id;
private String name;
private int qty;
public Barang(int id, String name, int qty) {
this.id = id;
this.name = name;
this.qty = qty;
}
public Barang(){
};
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getQty() {
return qty;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setQty(int qty) {
this.qty = qty;
}
#Override
public String toString() {
return "Barang{" + "id=" + id + ", name=" + name + ", qty=" + qty + '}';
}
Gudang Class
public class Gudang {
public static int id;
private int location;
public List<Barang> list = new ArrayList<Barang>();
public Gudang(int id, int location) {
Gudang.id = id;
this.location = location;
}
public int getId() {
return id;
}
public int getLocation() {
return location;
}
public List<Barang> getList() {
return list;
}
public void setId(int id) {
this.id = id;
}
public void setLocation(int location) {
this.location = location;
}
public void setList(List<Barang> list) {
this.list = list;
}
public void addBarang(Barang barang){
int id_barang = barang.getId();
if(this.list.isEmpty())
{
list.add(barang);
}
else
{
for(int i=0;i<list.size();i++)
{
if(list.get(i).getId() != id_barang)
{
list.add(barang);
System.out.println("Added");
break;
}
if(list.get(i).getId() == id_barang)
{
int new_qty = list.get(i).getQty()+barang.getQty();
list.get(i).setQty(new_qty);
}
}
}
System.out.println("Size List = "+list.size());
}
public void duplicate(List<Barang> list2)
{
this.list.addAll(list2);
}
public void clearBarang(){
this.list.clear();
}
public void display(){
for(Barang barang: this.list){
System.out.println(barang);
}
}
IE : If I have id=1 and qty=1, then input a new data with id=2 and qty=2, the final result will end up with id=2 and qty=3. No new data int he list were added.

try using .equals to compare if the data exist in your list

Please check if ids are duplicate between your old and new data.
If you ids are unique then you can take advantage of Map and put id as key and barang object as value. Whenever you successfully lookup map increment quantity field of object.

At first guess i would change:
if(list.get(i).getId() != id_barang)
to:
if(list.get(i).getId() != barang.getId())
maybe id_barang is not the same as the id stored in the barang object.

Related

Have a Queue with Generics implementation print specific Object attributes

I have created a simple Queue of type which is also contains a print() function to it.
public class ArrayQueue implements Queue {
private T[] theArray;
private int currentSize;
private int front;
private int back;
private static final int DEFAULT_CAPACITY = 10;
public ArrayQueue() {
theArray = (T[]) new Object[DEFAULT_CAPACITY];
currentSize = 0;
front = 0;
back = -1;
}
public boolean isEmpty() {
return currentSize == 0;
}
public T dequeue() throws EmptyQueueException {
if (isEmpty())
throw new EmptyQueueException("ArrayQueue dequeue error");
T returnValue = theArray[front];
front = increment(front);
currentSize--;
return returnValue;
}
public void enqueue(T x) {
if (currentSize == theArray.length)
doubleQueue();
back = increment(back);
theArray[back] = x;
currentSize++;
}
private int increment(int x) {
if (++x == theArray.length)
x = 0;
return x;
}
public void print() {
if (isEmpty()) {
System.out.printf("Empty queue\n");
return;
}
System.out.printf("The queue is: ");
for (int i = front; i != back; i = increment(i)) {
System.out.print(theArray[i] + " ");
}
System.out.print(theArray[back] + "\n");
}
I have also created a Song object with 3 variables
public class Song {
private int id;
private String name;
private int likes;
public Song() {
this(1,"Test",10);
}
public Song(int id,String name, int likes) {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLikes() {
return likes;
}
public void setLikes(int likes) {
this.likes = likes;
}
Is there a way modify this function in order to print a specific object's information or do i need to write a different print method during my implementation?
For example i would like my Print method to show all the objects variables , if i call just like this is will only get the object pointer
ArrayQueue<Song> arrayQueue = new ArrayQueue<Song>();
Queue<Song> queue = arrayQueue; //arrayQueue instance is also a Queue
Song s = new Song();
arrayQueue.enqueue(s);
arrayQueue.print();
Result is
The queue is: Song#15db9742
My modification would print :
The queue is : 1 Test 10
You need to override the toString() method of Song.
For example, add this to Song:
#Override
public String toString() {
return id + " " + name + " " + likes;
}

Checking if value in linked list is equal to String at each node

I'm writing a program for a homework assignment that has a binary search tree (Roster) that Student objects are inserted to by their String Id. Each student has a linked list that their courses are added to containing the String of the course and their grade. The binary search tree is my own version of an implementation.
I'm having trouble implementing my method to print the students that all contain a specific course. I think my implementation is off in my printCourseHelper() method as the if condition isn't working properly to check if the value in the list at each node is equal to the given value.
I'm looking for all student's enrolled in the course "Math161" which should be 3, and the String ID's of the student's in that class would be printed. I'm not getting any errors when I run my program, however only the functions being called above my displayStudents() are printing.
My issues I believe are in my BST.java, printCourse and printCourseHelper methods:
public void printCourse(String course) {
printCourseHelper(root, course);
}
public void printCourseHelper(Node n, String course) {
if(n.element.getCourseList().contains(course)) {
System.out.print(n.element.getId() + " ");
}
if (n.left != null) {
printCourseHelper(n.left, course);
}
if (n.right != null) {
printCourseHelper(n.right, course);
}
}
Homework5.class / main:
import java.util.LinkedList;
public class Homework5 {
static Roster rost = new Roster();
public static void main(String[] args) {
addStudent();
displayAllStudents();
lookupStudent("11114");
addCourse();
displayStudents("Math161");
}
// add students to the roster
static void addStudent() {
rost.addStudent(new Student("11111", "Jon", "Benson"));
rost.addStudent(new Student("11112", "Erick", "Hooper"));
rost.addStudent(new Student("11113", "Sam", "Shultz"));
rost.addStudent(new Student("11114", "Trent", "Black"));
rost.addStudent(new Student("11115", "Michell", "Waters"));
rost.addStudent(new Student("11116", "Kevin", "Johnson"));
}
// display all students in the roster
static void displayAllStudents() {
rost.displayAllStudents();
}
// lookup a student in the roster
static void lookupStudent(String id) {
if (rost.find(id) != null) {
System.out.println(id + " found");
} else {
System.out.println(id + " not found");
}
}
// add courses to the roster
static void addCourse() {
rost.addCourse("11111", new Course("CS116", 80));
rost.addCourse("11111", new Course("Math161", 90));
rost.addCourse("11112", new Course("Math161", 70));
rost.addCourse("11112", new Course("CS146", 90));
rost.addCourse("11112", new Course("CS105", 85));
rost.addCourse("11113", new Course("CS216", 90));
rost.addCourse("11114", new Course("CIS255", 75));
rost.addCourse("11114", new Course("CS216", 80));
rost.addCourse("11114", new Course("Math161", 60));
rost.addCourse("11114", new Course("COMM105", 90));
}
// display students enrolled in a given course id
static void displayStudents(String courseId) {
rost.displayStudents(courseId);
}
// display courses taken by a student
static void displayCourses(String id) {
rost.displayCourses("id");
}
// display the average grade for a student
static void getCourseAverage(String courseId) {
rost.getCourseAverage(courseId);
}
// display the average grade for a student
static void dropCoursesBelow(String id, int grade) {
rost.dropCoursesBelow(id, grade);
}
// drop a course from a student
static void dropCourse(String id, String courseId) {
rost.dropCourse(id, courseId);
}
// change the grade for a student
static void changeGrade(String id, String courseId, int grade) {
rost.changeGrade(id, courseId, grade);
}
}
Student.class
class Student implements Comparable<Student> {
String id;
String firstName;
String lastName;
LinkedList<Course> courses = new LinkedList<>();
Student(String id, String fName, String lName) {
this.id = id;
this.firstName = fName;
this.lastName = lName;
}
public String getName() {
return lastName;
}
public void setName(String lName) {
this.lastName = lName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public int compareTo(Student other) {
return this.getId().compareTo(other.getId());
}
public void addCourse(Course course) {
courses.add(course);
}
public LinkedList<Course> getCourseList() {
return courses;
}
}
Course.class:
class Course {
LinkedList<Course> course = new LinkedList<>();
String id; // course id
int grade;
Course(String id, int grade) {
this.id = id;
this.grade = grade;
}
public String getCourseId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getGrade() {
return grade;
}
public void setId(int grade) {
this.grade = grade;
}
}
Roster.class:
class Roster {
Student root;
int numStudents;
BST<Student> roster = new BST<>();
LinkedList<Course> courseList = new LinkedList<>();
public Roster() {
root = null;
numStudents = 0;
}
public void addStudent(Student st) {
roster.insert(st);
numStudents++;
}
public void displayAllStudents() {
roster.traverse(2);
}
public Student find(String id) {
return roster.find(id);
}
public void addCourse(String id, Course course) {
Student student = roster.find(id);
student.addCourse(course);
}
public void displayStudents(String courseId) {
roster.printCourse(courseId);
}
}
BST.java
class BST<Roster extends Comparable> {
private Node root;
public BST() {
root = null;
}
// Generic find method
public Student find(String id) {
Node current = root;
// Loop until e.compare to current element is not equal to 0
while (id.compareTo(current.element.getId()) != 0) {
//!!! implement
// if e.compare is less than 0 set current to current.left
if (id.compareTo(current.element.getId()) < 0) {
current = current.left;
} // else if current is 0 or greater than 0 set current
// to current.right
else {
current = current.right;
}
// if current is null, return null
if (current == null) {
return null;
}
}
// return current value when loop ends
return current.element;
}
public void insert(Student st) {
Node newNode = new Node(st);
if (root == null) {
root = newNode;
} else {
Node current = root;
Node parent = null;
while (true) {
parent = current;
if (st.getId().compareTo(current.element.getId()) < 0) {
current = current.left;
if (current == null) {
parent.left = newNode;
return;
}
} else {
current = current.right;
if (current == null) {
parent.right = newNode;
return;
}
}
}
}
}
public void printCourse(String course) {
printCourseHelper(root, course);
}
public void printCourseHelper(Node n, String course) {
if(n.element.getCourseList().contains(course)) {
System.out.print(n.element.getId() + " ");
}
if (n.left != null) {
printCourseHelper(n.left, course);
}
if (n.right != null) {
printCourseHelper(n.right, course);
}
}
public void traverse(int traverseType) {
switch (traverseType) {
case 1:
System.out.print("\nPreorder traversal: ");
// call preOrder(root) and implement preOrder()
preOrder(root);
break;
case 2:
System.out.print("\nList of all students: ");
inOrder(root);
break;
case 3:
System.out.print("\nPostorder traversal: ");
// call postOrder(root) and implement postOrder()
postOrder(root);
break;
}
System.out.println();
}
private void inOrder(Node localRoot) {
if (localRoot != null) {
inOrder(localRoot.left);
System.out.print(localRoot.element.getId() + " ");
inOrder(localRoot.right);
}
}
private void preOrder(Node localRoot) {
if (localRoot != null) {
System.out.print(localRoot.element + " ");
preOrder(localRoot.left);
preOrder(localRoot.right);
}
}
private void postOrder(Node localRoot) {
if (localRoot != null) {
postOrder(localRoot.left);
postOrder(localRoot.right);
System.out.print(localRoot.element + " ");
}
}
}
class Node {
protected Student element;
protected Node left;
protected Node right;
public Node(Student st) {
element = st;
}
}
The issue is that you are trying to see if a LinkedList of type Course contains a String. The contains method for LinkedList takes an Object as it's parameter type and that is why you are not getting a compilation issue.
The below code snippet is never true because a Course will never equal a String. I mention equal here because internally the LinkedList contains method checks equality for the Object you pass in against the Objects it contains.
if(n.element.returnList().contains(course)) {
System.out.print(n.element.getId() + " ");
}
Possible Solution using Map
Change courses to be a Map in Student class and then change the IF statement to check if the Map contains an element based on the course name. If the Map contains an object then it's true that the Student takes this course.
class Student implements Comparable<Student> {
String id;
String firstName;
String lastName;
Map<String, Course> courses = new HashMap<>();
Student(String id, String fName, String lName) {
this.id = id;
this.firstName = fName;
this.lastName = lName;
}
public String getName() {
return lastName;
}
public void setName(String lName) {
this.lastName = lName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public int compareTo(Student other) {
return this.getId().compareTo(other.getId());
}
public void addCourse(Course course) {
courses.put(course.getId(), course);
}
public Map<String, Course> getCourses() {
return courses;
}
}
IF statement
if(n.element.getCourses().get(course) != null) {
System.out.print(n.element.getId() + " ");
}
Possible Solution using List
Add new method to Student class.
public boolean takesCourse(String courseName){
for(Course course : courses){
if(courseName.equals(course.getId)) {
return true;
}
}
return false;
}
IF statement
if(n.element.takesCourse(course)) {
System.out.print(n.element.getId() + " ");
}

Created add() method to insert objects into an array and all i get are null values

this is a class called Doglist to add the object to an array.
public class DogList {
private int numItems;
private DogItem[] dogListArray;
private int position;
DogList () {
numItems=0;
position = 0;
dogListArray = new DogItem[10];
}
public void add (DogItem item) {
dogListArray[numItems++]= new DogItem(item.getName(),
item.getBreed(),
item.getWeight(),
item.getOwner1(),
item.getOwner2()
);
}
public String toString() {
String result = "";
for (int i=0; i<numItems; i++) {
result += dogListArray[i].toString() + "\n";
}
return result;
}
public DogItem searchForDogItem (DogItem gi) {
System.out.println("Here is your obj value: " + gi );
return null;
}//This is the one im having trouble with.
}
I have all the setters and getters in the DogItem class.
and this is from the UI where i get the dog info(name, breed, weight, owners1&2 names)
public void searchForItem (String name ) {
DogItem gi = new DogItem (name);
gi = gl.searchForDogItem(gi);
if (gi==null) {
msgTextField.setText("Dog Not Found");
} else {
nameTextField.setText(String.valueOf(gi.getName()));
breedTextField.setText(String.valueOf(gi.getBreed()));
weightTextField.setText(String.valueOf(gi.getWeight()));
owner1TextField.setText(String.valueOf(gi.getOwner1()));
owner2TextField.setText(String.valueOf(gi.getOwner2()));
}
}
Ill try and clear things up as i go.
this is the output i get
Here is your obj value: null null 0.0 null null
Ok so here is what it probably should look like instead. Just from what I saw wrong already. However you'd probably want to override the toString() method of DogItem.
Main method example of this:
public class Main {
public static void main(String[] args) {
DogItem dogItem = new DogItem("Spot", "Dalmation", "45", "Bob", "Sandy");
DogItem.add(dogItem);
DogItem result = DogItem.searchForItem("Spot");
if (result == null) {
System.out.println("Dog not found");
// GUI error output goes here
} else {
System.out.println("Here is your obj value: " + result);
// Where your GUI stuff goes
}
}
}
DogItem example of this:
public class DogItem {
private static DogItem[] dogListArray = new DogItem[100];
private static int numItems = 0;
private String name;
private String breed;
private String weight;
private String owner1;
private String owner2;
public DogItem(String name, String breed, String weight, String owner1, String owner2) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.owner1 = owner1;
this.owner2 = owner2;
}
public static void add(DogItem dogItem) {
dogListArray[numItems++] = dogItem;
}
public static DogItem searchForItem(String name) {
DogItem dogItem = null;
for (DogItem result : dogListArray) {
if (result != null) {
if (result.getName() == name) {
dogItem = result;
}
}
}
return dogItem;
}
#Override
public String toString() {
String result = name + ", " + breed + ", " + weight + ", " + owner1 + " " + owner2;
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getOwner1() {
return owner1;
}
public void setOwner1(String owner1) {
this.owner1 = owner1;
}
public String getOwner2() {
return owner2;
}
public void setOwner2(String owner2) {
this.owner2 = owner2;
}
}
These would be recommended changes from me though:
private static ArrayList<String> owners;
private static ArrayList<DogItem> dogsList;
public DogItem(String name, String breed, String weight, String owner) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.owners.add(owner);
}
public void init() {
owners = new ArrayList<String>();
dogsList = new ArrayList<DogItem>();
}
public void addDog(DogItem dogItem) {
dogsList.add(dogItem);
}
public DogItem searchForItem(String name) {
DogItem dogItem = null;
for (DogItem result : dogsList) {
if (result != null) {
if (result.getName() == name) {
dogItem = result;
}
}
}
return dogItem;
}
public void addOwner(String owner) {
owners.add(owner);
}
public String getOwner() {
return owners.get(owners.size() - 1);
}

Adding Items to my inventory in Java

I am making a text-based game on JavaFX, and after I hit a tree, I want to get Oak logs.
I have already built my inventory, and I have put default items in it such as Water, Bread, etc.
I am trying to add my Oak Logs to my inventory, but nothing is working.
Here is a part of my code:
Item ItemList[] = {new Bread(), new OakLog()};
Optional<ButtonType> result = alert.showAndWait();
if(result.get() == buttonTypeOak) {
woodcuttingXP = woodcuttingXP + oakXP;
dialogue.appendText("You swing at an Oak tree. + " + oakXP + "XP.\n");
dialogue.appendText("You gathered 1 log.\n");
mainCharacter.getInventory().add(new OakLog());
}
Here is my Item Class:
package game;
public class Item {
private String name;
private int weight;
private int quantity;
private int value;
private String description;
public Item(String name, int value, String description) {
this.name = name;
this.value = value;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String toString() {
return getName();
}
}
And finally, here is my Character class:
package game;
import java.util.ArrayList;
import beverages.Water;
import items.OakLog;
import rawFood.Bread;
public class Character {
private String name;
private int hydrationLevel;
private int healthLevel;
private int hungerLevel;
private int woodcuttingLevel;
public int getWoodcuttingLevel() {
return woodcuttingLevel;
}
public void setWoodcuttingLevel(int woodcuttingLevel) {
this.woodcuttingLevel = woodcuttingLevel;
}
public int getHungerLevel() {
return hungerLevel;
}
public void setHungerLevel(int hungerLevel) {
this.hungerLevel = hungerLevel;
}
private ArrayList<Item> inventory = new ArrayList<Item>();
public ArrayList<Item> getInventory() {
return inventory;
}
public void setInventory(ArrayList<Item> inventory) {
this.inventory = inventory;
}
//creates a person with two basic items
public Character(String name){
this.name = name;
this.hydrationLevel = 100;
this.healthLevel = 100;
this.hungerLevel = 100;
this.woodcuttingLevel = 1;
addToInventory (new Bread());
addToInventory (new OakLog());
addToInventory (new Water());
}
//GETTERS AND SETTERS
public String getName() {
return name;
}
public int getHydrationLevel() {
return hydrationLevel;
}
public void setHydrationLevel(int hydrationLevel) {
this.hydrationLevel = hydrationLevel;
}
public int getHealthLevel() {
return healthLevel;
}
public void setHealthLevel(int healthLevel) {
this.healthLevel = healthLevel;
}
//END GETTERS AND SETTERS
/*Method Name: eat()
*Method Inputs: a piece of food
*Method Purpose: Will allow the user to eat food
*/
public Item getItemFromInventory(int index){
Item item = inventory.get(index);
return item;
}
public void addToInventory(Item item){
if(inventory.contains(item)){
item.setQuantity(item.getQuantity()+1);
}
else{
item.setQuantity(1);
inventory.add(item);
}
}
public String toString(){
return "Character Stats:\nName:" + getName() + "\nHydration: " + getHydrationLevel() + "\nHealth: " + getHealthLevel() + "\nWoodcutting: " + getWoodcuttingLevel();
}
}
In your code, you have:
if(inventory.contains(item)){
item.setQuantity(item.getQuantity()+1);
}
This just updates the quantity of the local variable item in the method, not the item in the inventory.

Sort ArrayList of objects by field in custom order

How can I achieve a custom sorting to the content of field name:
first element: P followed by numbers [1-9]{2} always on first
followed by : P followed by numbers 0[0-9]
followed by : S
followed by numbers [1-9]{2}
and then the rest in normal order i1.getName().compareToIgnoreCase(i2.getName())
private static Comparator<Item> itemComperator = new Comparator<Item>() {
#Override
public int compare(Item i1, Item i2) {
if (i1.getName().matches("P[1-9]{2}") && i2.getName().matches("P0[0-9]"))
return -1;
else if (i1.getName().matches("S[1-9]{2}"))
return -1;
else
return i1.getName().compareToIgnoreCase(i2.getName());
}
};
#Test
public void sortItem() {
Item item01 = new Item(1, "R59");
Item item02 = new Item(2, "S48");
Item item03 = new Item(3, "P01");
Item item04 = new Item(4, "P25");
Item item05 = new Item(5, "R99");
List<Item> items = Arrays.asList(item01, item02, item03, item04, item05);
System.out.println("before sorting");
long seed = System.nanoTime();
Collections.shuffle(items, new Random(seed));
for (Item i : items) {
System.out.println(i.getId() + " " + i.getName());
}
System.out.println("after sorting");
Collections.sort(items, itemComperator);
for (Item i : items) {
System.out.println(i.getId() + " " + i.getName());
}
}
public class Item {
private int id;
private String name;
public Item(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
output expected:
after sorting
4 P25
3 P01
2 S48
1 R59
5 R99
I think that I would first map each of the inputs to a "kind" number, which is based upon the list of criteria above. For example:
int kind(String input) {
if (input.matches("P[1-9]{2}") {
return 0;
} else if (input.matches("P0[0-9]")) {
return 1;
} else if (input.matches("S.*")) {
return 2;
} else if (input.matches("[1-9]{2}")) {
return 3;
} else {
return 4;
}
}
This gives you a way to see if the two strings are of the same "kind"; if not, return the ordering based on the kind. If they are the same kind, just compare them using (case insensitive) lexicographic ordering (you don't specify, but I assume you want e.g. "P11" to come before "P22"):
public int compare(Item a, Item b) {
String nameA = a.getName();
String nameB = b.getName();
int kindA = kind(nameA);
int kindB = kind(nameB);
if (kindA != kindB) {
return Integer.compare(kindA, kindB);
} else {
return nameA.compareToIgnoreCase(nameB);
}
}

Categories