Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
1806120
set up 1
GuoYuHeJason Nov 4, 2024
987d83e
Entities completed
GuoYuHeJason Nov 5, 2024
a2cc47e
Update .gitignore
GuoYuHeJason Nov 5, 2024
c5aba0d
set up 2
GuoYuHeJason Nov 5, 2024
18de28f
set up 3 and Demo
GuoYuHeJason Nov 5, 2024
a10afd8
Complete use case interface, basic view
Mikawu73 Nov 9, 2024
291838c
joke view
alexandersunliang Nov 10, 2024
9734d1d
joke view
alexandersunliang Nov 10, 2024
4201f4b
joke view
alexandersunliang Nov 10, 2024
31698ae
Update README.md
cheryllin2154 Nov 10, 2024
eefbb79
Merge pull request #2 from GuoYuHeJason/Mika
K1bbu7z Nov 10, 2024
9214ace
Merge pull request #4 from GuoYuHeJason/Cheryl
GuoYuHeJason Nov 10, 2024
6618741
Merge pull request #3 from GuoYuHeJason/alexander.sun
K1bbu7z Nov 10, 2024
39ce625
Merge pull request #1 from GuoYuHeJason/guoyu
GuoYuHeJason Nov 10, 2024
5d93c9d
joke view name update
alexandersunliang Nov 10, 2024
6dcdd8d
joke ui update
alexandersunliang Nov 10, 2024
35bc7ce
Merge pull request #5 from GuoYuHeJason/alexander.sun
GuoYuHeJason Nov 10, 2024
8b304b6
FavouriteView first update
K1bbu7z Nov 10, 2024
a4ce096
Merge pull request #6 from GuoYuHeJason/xuesi
GuoYuHeJason Nov 12, 2024
d3f6ce6
Merge remote-tracking branch 'origin/main' into alexander.sun2
alexandersunliang Nov 12, 2024
5484947
Add files via upload
cheryllin2154 Nov 12, 2024
f8224cc
readme updated
cheryllin2154 Nov 12, 2024
924b297
Add UserFactory and Create Favourite use_case folder
K1bbu7z Nov 12, 2024
950ae9b
set up 3 and Demo
GuoYuHeJason Nov 12, 2024
a3146e7
Structure
GuoYuHeJason Nov 12, 2024
edaf940
DemoSearchView complete
Mikawu73 Nov 12, 2024
fe3a872
Merge pull request #11 from GuoYuHeJason/Mika
GuoYuHeJason Nov 12, 2024
f23c60b
Merge remote-tracking branch 'origin/main' into xuesi
K1bbu7z Nov 12, 2024
f13c5d4
Merge pull request #10 from GuoYuHeJason/guoyu
K1bbu7z Nov 12, 2024
452e9cf
Create ProjectLog
GuoYuHeJason Nov 12, 2024
9765502
Merge remote-tracking branch 'origin/main' into xuesi
K1bbu7z Nov 12, 2024
a275e92
class over
K1bbu7z Nov 12, 2024
366c131
Update ProjectLog
GuoYuHeJason Nov 12, 2024
be0bf92
Update ProjectLog
GuoYuHeJason Nov 12, 2024
337ea31
FavouriteView Update
K1bbu7z Nov 12, 2024
26943f0
Merge pull request #9 from GuoYuHeJason/Cheryl
GuoYuHeJason Nov 13, 2024
05fd353
Merge pull request #8 from GuoYuHeJason/cheryllin2154-view
GuoYuHeJason Nov 13, 2024
1b059d0
Merge remote-tracking branch 'origin/xuesi' into guoyu
GuoYuHeJason Nov 13, 2024
839a56f
Implementing JokeView
GuoYuHeJason Nov 14, 2024
3b4f0ce
Semi-Final Generate UseCase
GuoYuHeJason Nov 15, 2024
f64933f
Changing generate usecase to use output data
GuoYuHeJason Nov 15, 2024
69f5197
Changing generate usecase to use output data
GuoYuHeJason Nov 15, 2024
efdbd27
Update ProjectLog
GuoYuHeJason Nov 15, 2024
770232e
joke ui update
alexandersunliang Nov 17, 2024
503bc40
search favourite function typo fix
alexandersunliang Nov 17, 2024
bcc9d33
Search Use case mostly complete, and DataaccessObject complete
Mikawu73 Nov 17, 2024
c52d56b
a little bug fixed for search use case
Mikawu73 Nov 17, 2024
5091fe7
Ported logout and signup use case from lab5
Mikawu73 Nov 18, 2024
9464649
Merge pull request #7 from GuoYuHeJason/alexander.sun2
GuoYuHeJason Nov 19, 2024
a662fe0
Merge pull request #13 from GuoYuHeJason/guoyu
GuoYuHeJason Nov 19, 2024
8773e20
Merge pull request #12 from GuoYuHeJason/GuoYuHeJason-patch-1
GuoYuHeJason Nov 19, 2024
f32c025
Merge pull request #14 from GuoYuHeJason/Mika
Mikawu73 Nov 19, 2024
2700b73
add to fav
cheryllin2154 Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Csc207 Group project view 2.pdf
Binary file not shown.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ out/
.idea/easycode.ignore

target/
token.txt
.idea/compiler.xml
.idea/encodings.xml
.idea/misc.xml
.idea/workspace.xml

### Eclipse ###
.apt_generated
Expand All @@ -29,4 +34,4 @@ bin/
.vscode/

### Mac OS ###
.DS_Store
.DS_Store
2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions ProjectLog
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Jason GenerateDataAccessObjects, sending requests to joke api, google gemni api
All initial draft design
Alex intitial main gui (View, ViewModel)
Cheyl Read.md completed
Cheyl Finalized UI design
Jason User and Joke entity
K1bbu7z User factory, Favrite UI
Jason: generate usecse, explain use case


TODO
If time permits:
K1bbu7z : Funnist Use Case, fav use case
Mika: Search Use Case, sign up usecase, log out usecase, user data access object
Alex: Fav_search Use Case, login usecase
Cheyl: add to fav Use Case, Fav joke display pannel
Jason: ViewManagerModel, AppBuilder

If not 1:
no login, sign up, log out, user data access object, user entity has no username and password. everything gone upon closing.
No funniest?
K1bbu7z : fav use case (including display pannel)
Mika: Search Use Case
Alex: Fav_search Use Case
Cheyl: add to fav Use Case
Jason: ViewManagerModel, AppBuilder

If not 2 (not well thought out):
No funniest, No fav_search
K1bbu7z : fav use case (just display), AppBuilder
Mika: Search Use Case, user data access object
Alex: login,sign up usecase,
Cheyl: add to fav Use Case, log out usecase
Jason: ViewManagerModel

notes
Login Signup logout logic (3 use cases)(create user from DB/File Data, write Data from curr User).
DataAccessObject (getting user info)


90 changes: 64 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,74 @@
# Note Application
# Joke Machine

This is a minimal example demonstrating usage of the
password-protected user part of the API used in lab 5.
### Project for Group #269
#### Team Name: Joke Machine
#### Domain: Joke Generation and Explanation

You can find more information about the API endpoints in
[the documentation](https://www.postman.com/cloudy-astronaut-813156/csc207-grade-apis-demo/documentation/fg3zkjm/5-password-protected-user).

If your team is considering an application for which it would be convenient to
store data in something like a database, you may find that the API calls demonstrated
here will be useful in your project, as this will allow you to store
an arbitrary JSON object associated with a username and password.

In this application, a single note has a name (the "username" in terms of the API) and the note
can be read by anyone who knows the name — but only edited by someone who
knows the password for it.
## Table of Contents

You can see the documentation in the various files for more information.
* Software Specification
* Features
* User Stories
* Entities
* Proposed API
* Setup and Installation
* Usage
* Contributing
* License
* Contact

## Testing
## Software Specification
Joke Machine is a joke generation and explanation platform that allows users to generate, search for, save, and understand jokes. Users can generate or search up jokes, ask for explanations, and sort their list of favorite jokes based on rating of the jokes. Joke Machine integrates with external APIs for joke generation and explanation to provide rich and diverse humor content.

The repo also includes an example of a use case interactor test, as well as
an example of an end-to-end test which automates button clicks and inspects
the contents of the actual views. This is something we discussed in the lectures
about testing in CA but had not provided a code example of before. Note, one
could also inspect the contents of the ViewModel objects instead when testing
CA to make a similar test which would be less dependent on the details of the
specific UI implementation.
## Features
Joke Generation: Generate new jokes with a variety of themes and styles.
Joke Explanation: Explain jokes, whether generated by the app or provided by the user.
Favorites Management: Save favorite jokes to revisit later.
Search and Filter:
Search for jokes by title or keywords (e.g., themes like "911").
Search for jokes within saved list of jokes
Filter jokes by rating to find the "funniest" jokes.

## Project Starter Code
## User Stories
* Bob generates a joke. He then keeps generating new jokes with different specifications until he is tired.
* Bob was told a joke but he doesn't understand it. He runs the joke explanation program and the program explains to him what is funny about the joke.
* Bob finds some jokes funny and saves them as favorite. He later wants to revisit the jokes that were favorited, so he revisits his list of saved jokes.
* Bob remembers a joke vaguely, he only remembers that it was about 911. He searches “911” and a few different jokes pop up.
* Bob wants to find a specific saved joke, he doesn’t remember what the joke said but he remembers the explanation. He then goes into his list of saved jokes and searches by keywords in the explanation.
* Bob wants to find some really funny jokes. He presses the “Funniest” button in the saved view, then the program returns the joke with the highest score.

Your team may choose to use this repo as starter code for your project. You could
also use the lab 5 code — or start from an empty repo if your team prefers.
## Entities
### User
Attributes:
name: User's name for login.
password: User’s password.
favorite: A list of saved jokes marked as favorites.
### Joke
Attributes:
content: The joke text.
explanation: The joke's explanation or humorous insight.
score: Humor rating to indicate how funny the joke is.

## Proposed API
* Google Gemini: Used for natural language understanding and generation. Assists in explaining user-provided jokes.
* JokeAPI: Used for joke retrieval and generation, allowing for a diverse and randomized joke collection.

If you choose to use one of the repositories we have provided, you can either make
a fork of it or copy the subset of code you want into a completely new repository.
## Setup and Installation
* Clone the Repository
* Install Dependencies:
* Run the Application:

## Usage
### Generating Jokes
* Select the "Generate" button to create a new joke or search up joke by title or keyword
### Explaining Jokes
* If you don’t understand a joke, click on the "Explain Joke" button.
The system will provide an explanation of the joke's humor or meaning.
### Saving Favorites
* Click "favorite" to add a joke to your favorites list.
* Access your favorites anytime from the "favorited" section.
### Searching and Filtering
* Keyword Search: Enter a keyword (e.g., "911") to find jokes related to that theme.
* Funniest Jokes: Use the "Funniest" filter to sort saved jokes by their humor rating.
79 changes: 79 additions & 0 deletions src/main/java/data_access/ExplanationDataAccessObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package data_access;

import okhttp3.*;
import org.json.JSONException;
import org.json.JSONObject;
import use_case.explanation.ExplanationDataAccessInterface;

import java.io.IOException;

public class ExplanationDataAccessObject implements ExplanationDataAccessInterface {

private static final String TOKEN = "token";
private static final String GOOGLE_API_KEY = System.getenv(TOKEN);
private static final String API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=" + GOOGLE_API_KEY;
private static final String APPLICATION_JSON = "application/json";

// uses java sdk instead of https
// const genAI = new GoogleGenerativeAI(process.env.API_KEY);
//const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
//
//const prompt = "Write a story about a magic backpack.";
//
//const result = await model.generateContent(prompt);
//console.log(result.response.text());

@Override
public String getExplanation(String joke) {

String prompt = "explain this joke" + joke;

// Build client
final OkHttpClient client = new OkHttpClient().newBuilder()
.build();

// type of request body is json
final MediaType mediaType = MediaType.parse(APPLICATION_JSON);
//make request body
final JSONObject requestBody = new JSONObject()
// .put("generationConfig", new JSONObject().put("maxOutputTokens", 1))
.put("contents", new JSONObject()
.put("parts", new JSONObject()
.put("text", prompt)
)
);
// RequestBody takes in type and content (string)
final RequestBody body = RequestBody.create(mediaType, requestBody.toString());

// add arguments to url, or add headers as needed
final Request request = new Request.Builder()
.url(String.format(API_URL))
.post(body)
.build();

// Hint: look at the API documentation to understand what the response looks like.
try {

// Client creates a Call with Request
// Call returns the Response from execute()
final Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
final JSONObject responseBody = new JSONObject(response.body().string());

JSONObject candidates = responseBody.getJSONArray("candidates").getJSONObject(0);
if (candidates.getString("finishReason").equals("STOP")) {
return candidates
.getJSONObject("content")
.getJSONArray("parts").getJSONObject(0)
.getString("text");
} else {
return "this joke is too inappropriate for me!";
}
} else {
throw new RuntimeException(response.message());
}
} catch (IOException | JSONException event) {
throw new RuntimeException(event);
}
}
}
96 changes: 96 additions & 0 deletions src/main/java/data_access/JokeDataAccessObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package data_access;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONException;
import org.json.JSONObject;
import use_case.generate.GenerateDataAccessInterface;
import use_case.search.SearchDataAccessInterface;

import java.io.IOException;


public class JokeDataAccessObject implements GenerateDataAccessInterface,
SearchDataAccessInterface {

private static final String MESSAGE = "message";
private static final String API_URL = "https://v2.jokeapi.dev/joke/Any";
private static final String API_SEARCH_URL = "https://v2.jokeapi.dev/joke/Any?contains=";

@Override
public String getJokeContent() {

// Build client
// Build the request to get joke.
// client sends request
final OkHttpClient client = new OkHttpClient().newBuilder()
.build();
// add arguments to url, or add headers as needed
final Request request = new Request.Builder()
.url(String.format(API_URL))
.build();

// Hint: look at the API documentation to understand what the response looks like.
try {
// Client creates a Call with Request
// Call returns the Response from execute()
final Response response = client.newCall(request).execute();

// JSONObject is a dictionary that can be written to a JSON file
// a JSON file has multiple JSONObjects:
// file -> String -> JSONArray -> JSONObject
// String jsonString = Files.readString(Paths.get(getClass().getClassLoader().getResource(filename).toURI()))
// JSONArray jsonArray = new JSONArray(jsonString);
// JSONObject jsonObject = jsonArray.getJSONObject(i);
final JSONObject responseBody = new JSONObject(response.body().string());

// Response body (the JSONObject) varies for API.
if (responseBody.getBoolean("error")) {
throw new RuntimeException(responseBody.getString(MESSAGE));
} else {
switch (responseBody.getString("type")) {
case "single":
return responseBody.getString("joke");
case "twopart":
return responseBody.getString("setup") + responseBody.getString("delivery");
default:
return "something funny";
}
}
}
catch (IOException | JSONException event) {
throw new RuntimeException(event);
}
}

@Override
public String searchJoke(String keyword) {
final OkHttpClient client = new OkHttpClient().newBuilder()
.build();
final Request request = new Request.Builder()
.url(String.format(API_SEARCH_URL + keyword))
.build();
try {
final Response response = client.newCall(request).execute();
final JSONObject responseBody = new JSONObject(response.body().string());

if (responseBody.getBoolean("error")) {
throw new RuntimeException(responseBody.getString(MESSAGE));
}
else {
switch (responseBody.getString("type")) {
case "single":
return responseBody.getString("joke");
case "twopart":
return responseBody.getString("setup") + responseBody.getString("delivery");
default:
return "something funny";
}
}
}
catch (IOException | JSONException event) {
throw new RuntimeException(event);
}
}
}
11 changes: 11 additions & 0 deletions src/main/java/data_access/MockExplanationDataAccessObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package data_access;

import use_case.explanation.ExplanationDataAccessInterface;

public class MockExplanationDataAccessObject implements ExplanationDataAccessInterface {

@Override
public String getExplanation(String joke) {
return "haha, that's funny";
}
}
27 changes: 27 additions & 0 deletions src/main/java/entity/Joke.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package entity;

// there should be a joke factory, a user factory
public class Joke {

private final String content;
private String explanation;
private final int score;

public Joke(String content, int score) {
this.content = content;
this.explanation = "explanation";
this.score = score;
}

public String getContent() {
return content;
}

public String getExplanation() {
return explanation;
}

public void setExplanation(String explanation) {
this.explanation = explanation;
}
}
7 changes: 7 additions & 0 deletions src/main/java/entity/JokeFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package entity;

public class JokeFactory {
public Joke create(String content, int score) {
return new Joke(content, score);
}
}
Loading