diff --git a/.gitignore b/.gitignore index 8b13789..6af3edd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ - +cmpe443 +cmpe487/final-project diff --git a/README.md b/README.md index 2a8788a..2584a59 100644 --- a/README.md +++ b/README.md @@ -42,17 +42,17 @@ Programming projects that I have written at university - [Project 1](/cmpe321/project1) `Latex` - [Project 2](/cmpe321/project2) `Java` - [Project 3](/cmpe321/project3) `PHP` -- + ### [CmpE322 - Operating Systems](/cmpe322) - [Project 1](/cmpe322/project1) `C++` - [Project 2](/cmpe322/project2) `C++` - [Project 3](/cmpe322/project3) `C++` -- + ### [CmpE362 - Intro to Signal Processing](/cmpe362) - [Project 1](/cmpe362/project1) `Matlab` - [Project 2](/cmpe362/project2) `Matlab` - [Project 3](/cmpe362/project3) `Matlab` -- + ### [CmpE493 - Introduction to Information Retrieval](/cmpe493) - [Project 1](/cmpe493/project1) `Python` - [Project 2](/cmpe493/project2) `Python` diff --git a/cmpe230/project1/test.stm b/cmpe230/project1/test.stm new file mode 100644 index 0000000..e69de29 diff --git a/cmpe436/final-project/Auctioner/.gitignore b/cmpe436/final-project/Auctioner/.gitignore new file mode 100644 index 0000000..fd45b12 --- /dev/null +++ b/cmpe436/final-project/Auctioner/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea/caches/build_file_checksums.ser +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/cmpe436/final-project/Auctioner/README.md b/cmpe436/final-project/Auctioner/README.md new file mode 100644 index 0000000..34bae4a --- /dev/null +++ b/cmpe436/final-project/Auctioner/README.md @@ -0,0 +1,4 @@ +## Real-time Auction Android App +It has 2 different activities. + +`MainActivity` is using for auction listing and `DetailActivity` is using for auction bidding page. diff --git a/cmpe436/final-project/Auctioner/app/.gitignore b/cmpe436/final-project/Auctioner/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/cmpe436/final-project/Auctioner/app/build.gradle b/cmpe436/final-project/Auctioner/app/build.gradle new file mode 100644 index 0000000..824fd83 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/build.gradle @@ -0,0 +1,32 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.enescakir.auctioner" + minSdkVersion 15 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.android.support:recyclerview-v7:28.0.0' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.google.code.gson:gson:2.8.5' + implementation 'com.android.support:design:28.0.0' +} diff --git a/cmpe436/final-project/Auctioner/app/proguard-rules.pro b/cmpe436/final-project/Auctioner/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/cmpe436/final-project/Auctioner/app/src/androidTest/java/com/enescakir/auctioner/ExampleInstrumentedTest.java b/cmpe436/final-project/Auctioner/app/src/androidTest/java/com/enescakir/auctioner/ExampleInstrumentedTest.java new file mode 100644 index 0000000..db73b60 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/androidTest/java/com/enescakir/auctioner/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.enescakir.auctioner; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.enescakir.auctioner", appContext.getPackageName()); + } +} diff --git a/cmpe436/final-project/Auctioner/app/src/main/AndroidManifest.xml b/cmpe436/final-project/Auctioner/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2793a8c --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/ic_launcher-web.png b/cmpe436/final-project/Auctioner/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..ce8faa8 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/ic_launcher-web.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/AuctionAdapter.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/AuctionAdapter.java new file mode 100644 index 0000000..ebb6158 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/AuctionAdapter.java @@ -0,0 +1,79 @@ +package com.enescakir.auctioner; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.enescakir.auctioner.Model.Auction; + +import java.util.ArrayList; + +public class AuctionAdapter extends RecyclerView.Adapter { + + ArrayList auctions; + LayoutInflater inflater; + + public AuctionAdapter(Context context, ArrayList auctions) { + inflater = LayoutInflater.from(context); + this.auctions = auctions; + } + + + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = inflater.inflate(R.layout.row_auction, parent, false); + return new MyViewHolder(view); + } + + @Override + public void onBindViewHolder(MyViewHolder holder, int position) { + holder.setData(auctions.get(position), position); + } + + @Override + public int getItemCount() { + return auctions.size(); + } + + + class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView nameView, dateView; + ImageView imageView; + Auction auction; + int position; + + public MyViewHolder(View view) { + super(view); + nameView = (TextView) view.findViewById(R.id.nameView); + dateView = (TextView) view.findViewById(R.id.dateView); + imageView = (ImageView) view.findViewById(R.id.imageView); + view.setOnClickListener(this); + } + + public void setData(Auction auction, int position) { + this.auction = auction; + this.position = position; + this.nameView.setText(auction.getName()); + this.dateView.setText(String.format("Until: %s", auction.getHumanDate())); + Context context = imageView.getContext(); + int image = context.getResources().getIdentifier(auction.getImageName(), "drawable", context.getPackageName()); + this.imageView.setImageResource(image); + } + + @Override + public void onClick(View view) { + Context context = view.getContext(); + Intent intent = new Intent(view.getContext(), DetailActivity.class); + intent.putExtra("auctionId", auction.getId()); + intent.putExtra("auctionName", auction.getName()); + intent.putExtra("auctionDescription", auction.getDescription()); + intent.putExtra("auctionDate", auction.getDate()); + context.startActivity(intent); + } + } +} \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/BaseActivity.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/BaseActivity.java new file mode 100644 index 0000000..e72983b --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/BaseActivity.java @@ -0,0 +1,34 @@ +package com.enescakir.auctioner; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.support.v7.app.AppCompatActivity; +import android.widget.Toast; + +import com.enescakir.auctioner.Model.User; + +public class BaseActivity extends AppCompatActivity { + public static String username; + public static int points; + public SharedPreferences preferences; + ProgressDialog progressDialog; + + public void showToast(Context context, String message) { + Toast.makeText(context, message, Toast.LENGTH_LONG).show(); + } + + public void showProgress(Context context) { + progressDialog = ProgressDialog.show(context, "", "Loading. Please wait...", true); + } + + public void dismissProgress() { + if (progressDialog != null) { + progressDialog.dismiss(); + } + } + + public final void runOnThread(Thread action) { + action.start(); + } +} diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/BidAdapter.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/BidAdapter.java new file mode 100644 index 0000000..8fc0e9c --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/BidAdapter.java @@ -0,0 +1,68 @@ +package com.enescakir.auctioner; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.enescakir.auctioner.Model.Bid; + +import java.util.ArrayList; + +public class BidAdapter extends RecyclerView.Adapter { + + ArrayList bids; + LayoutInflater inflater; + + public BidAdapter(Context context, ArrayList bids) { + inflater = LayoutInflater.from(context); + this.bids = bids; + } + + + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = inflater.inflate(R.layout.row_bid, parent, false); + return new MyViewHolder(view); + } + + @Override + public void onBindViewHolder(MyViewHolder holder, int position) { + holder.setData(bids.get(position), position); + + } + + @Override + public int getItemCount() { + return bids.size(); + } + + public void addBid(Bid bid) { + bids.add(0, bid); + notifyItemInserted(0); + } + + class MyViewHolder extends RecyclerView.ViewHolder { + TextView usernameView, pointView, dateView; + Bid bid; + int position; + + public MyViewHolder(View view) { + super(view); + usernameView = (TextView) view.findViewById(R.id.usernameView); + pointView = (TextView) view.findViewById(R.id.pointView); + dateView = (TextView) view.findViewById(R.id.dateView); + } + + public void setData(Bid bid, int position) { + this.bid = bid; + this.position = position; + this.usernameView.setText(bid.getUsername()); + this.pointView.setText(String.format("%d points", bid.getPoint())); + this.dateView.setText(bid.getHumanDate()); + } + } +} \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/DetailActivity.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/DetailActivity.java new file mode 100644 index 0000000..f41ce45 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/DetailActivity.java @@ -0,0 +1,283 @@ +package com.enescakir.auctioner; + +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.support.v7.app.ActionBar; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.enescakir.auctioner.Model.Auction; +import com.enescakir.auctioner.Model.Packet; +import com.enescakir.auctioner.Model.SocketThread; +import com.enescakir.auctioner.Model.Bid; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import static com.enescakir.auctioner.Model.Packet.Type.*; + +public class DetailActivity extends BaseActivity { + + TextView descView; + TextView pointView; + TextView timeView; + ImageView imageView; + RecyclerView bidsView; + Button bidButton; + Auction auction; + Dialog bidDialog; + BidThread bidThread; + BidAdapter bidAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_detail); + + preferences = getSharedPreferences("user", MODE_PRIVATE); + + getAuctionDetails(); + setTitle(); + setAuctionDetails(); + handleBidClick(); + setBidDialog(); + + bidThread = new BidThread(); + bidThread.start(); + } + + private void getAuctionDetails() { + Intent intent = getIntent(); + int id = intent.getIntExtra("auctionId", 0); + String name = intent.getStringExtra("auctionName"); + String description = intent.getStringExtra("auctionDescription"); + String date = intent.getStringExtra("auctionDate"); + auction = new Auction(id, name, description, date); + } + + private void setTitle() { + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + ActionBar actionBar = getSupportActionBar(); + actionBar.setTitle(auction.getName()); + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + private void setAuctionDetails() { + bidButton = findViewById(R.id.bidButton); + descView = findViewById(R.id.descView); + descView.setText(auction.getDescription()); + pointView = findViewById(R.id.tvPoint); + pointView.setText(String.format("Your points: %d", points)); + imageView = findViewById(R.id.imageView); + imageView.setImageResource(getResources().getIdentifier(auction.getImageName(), "drawable", getPackageName())); + timeView = findViewById(R.id.timeView); + long diff = auction.getDateObject().getTime() - new Date().getTime(); + CountDown counter = new CountDown(diff, 1000); + counter.start(); + } + + private void setBidDialog() { + bidDialog = new Dialog(this); + bidDialog.setContentView(R.layout.dialog_bid); + bidDialog.setCancelable(true); + final TextView nameTextView = bidDialog.findViewById(R.id.tvName); + final EditText pointInput = bidDialog.findViewById(R.id.etPoint); + final Button cancelButton = bidDialog.findViewById(R.id.bCancel); + final Button offerButton = bidDialog.findViewById(R.id.bOffer); + nameTextView.setText(String.format("Bid Offer for \"%s\"", auction.getName())); + + cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + bidDialog.dismiss(); + pointInput.setText(""); + } + }); + offerButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + bidDialog.dismiss(); + if (!TextUtils.isEmpty(pointInput.getText())) { + int offer = Integer.parseInt(pointInput.getText().toString()); + pointInput.setText(""); + final Bid bid = new Bid(username, offer, new Date()); + runOnThread(new Thread() { + @Override + public void run() { + bidThread.sendMessage(new Packet(BID_STORE, bid).toJson()); + } + }); + } else { + showError("You have to give offer that is greater than zero"); + } + } + }); + + } + + private void handleBidClick() { + bidButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View view) { + bidDialog.show(); + } + }); + } + + private void setBidsView(ArrayList bids) { + bidsView = findViewById(R.id.bidsView); + bidAdapter = new BidAdapter(this, bids); + bidsView.setAdapter(bidAdapter); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + bidsView.setLayoutManager(linearLayoutManager); + } + + @Override + public boolean onSupportNavigateUp() { + runOnThread(new Thread() { + @Override + public void run() { + bidThread.close(); + } + }); + finish(); + return true; + } + + public class CountDown extends CountDownTimer { + CountDown(long millisInFuture, long countDownInterval) { + super(millisInFuture, countDownInterval); + } + + @Override + public void onFinish() { + timeView.setText("Finished!"); + } + + @Override + public void onTick(long millisUntilFinished) { + long millis = millisUntilFinished; + String hms = String.format("%d days %02d:%02d:%02d", + TimeUnit.MILLISECONDS.toDays(millis), + (TimeUnit.MILLISECONDS.toHours(millis) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(millis))), + (TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))), + (TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))) + ); + timeView.setText(hms); + } + } + + class BidThread extends SocketThread { + @Override + public void run() { + super.run(); + try { + sendMessage(new Packet(BID_LISTEN, Integer.toString(auction.getId())).toJson()); + + final Packet response = Packet.fromJson(in.readLine()); + runOnUiThread(new Runnable() { + @Override + public void run() { + setBidsView(response.toArrayList(Bid.class)); + } + }); + this.listen(); + + } catch (Exception e1) { + Log.e("LOOP", "First loop error"); + try { + this.listen(); + } catch (Exception e2) { + Log.e("LOOP", "Second loop error"); + } + } + } + + public void listen() throws IOException { + String message; + while ((message = in.readLine()) != null) { + Packet packet; + try { + packet = Packet.fromJson(message); + } catch (Exception e) { + packet = new Packet(UNKNOWN, ""); + Log.e("PACKET", "Parse error"); + } + switch (packet.getType()) { + case BID_STORE: + final int result = packet.toObject(Integer.class); + if (result == -2) { + showError(String.format("You had to bid more than last bid that is %d points", bidAdapter.bids.get(0).getPoint())); + } else if (result == -1) { + showError(String.format("You have %d points, so it's not enough", points)); + } else { + runOnThread(new Thread() { + @Override + public void run() { + points = result; + preferences.edit().putInt("points", result).apply(); + runOnUiThread(new Runnable() { + @Override + public void run() { + pointView.setText(String.format("Your points: %d", points)); + } + }); + } + }); + } + break; + case BID_NEW: + final Bid bid = packet.toObject(Bid.class); + runOnUiThread(new Runnable() { + @Override + public void run() { + bidAdapter.addBid(bid); + bidsView.scrollToPosition(0); + } + }); + break; + default: + Log.e("UNKNOWN_PACKET", "Unknown packet from :" + message); + } + } + } + } + + public void showError(String message) { + final String m = message; + runOnUiThread(new Runnable() { + @Override + public void run() { + final Dialog alert = new Dialog(DetailActivity.this); + alert.setContentView(R.layout.dialog_alert); + alert.setCancelable(true); + final TextView nameTextView = alert.findViewById(R.id.tvMessage); + final Button closeButton = alert.findViewById(R.id.bClose); + nameTextView.setText(m); + closeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + alert.dismiss(); + } + }); + alert.show(); + } + }); + } +} \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/MainActivity.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/MainActivity.java new file mode 100644 index 0000000..a42f9d3 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/MainActivity.java @@ -0,0 +1,177 @@ +package com.enescakir.auctioner; + +import android.app.Dialog; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.enescakir.auctioner.Model.Auction; +import com.enescakir.auctioner.Model.Packet; +import com.enescakir.auctioner.Model.SocketThread; +import com.enescakir.auctioner.Model.User; + +import java.util.ArrayList; + +import static com.enescakir.auctioner.Model.Packet.Type.AUCTIONS; +import static com.enescakir.auctioner.Model.Packet.Type.USER; + + +public class MainActivity extends BaseActivity { + RecyclerView auctionsView; + Dialog loginDialog; + private Toolbar toolbar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + final AuctionThread thread = new AuctionThread(); + thread.start(); + + preferences = getSharedPreferences("user", MODE_PRIVATE); + + if (preferences.getString("username", null) == null) { + authUser(); + } else { + username = preferences.getString("username", null); + points = preferences.getInt("points", 1000); + showToast(MainActivity.this, "Welcome " + username); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + + if (id == R.id.action_logout) { + username = null; + points = 0; + preferences.edit().remove("username").apply(); + preferences.edit().remove("points").apply(); + authUser(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void authUser() { + loginDialog = new Dialog(this); + loginDialog.setContentView(R.layout.dialog_login); + loginDialog.setCancelable(false); + loginDialog.show(); + final EditText nameInput = loginDialog.findViewById(R.id.etUsername); + final EditText passwordInput = loginDialog.findViewById(R.id.etPassword); + final Button button = loginDialog.findViewById(R.id.button); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String username = nameInput.getText().toString(); + String password = passwordInput.getText().toString(); + + if (TextUtils.isEmpty(username)) { + nameInput.setError("Username is required!"); + showToast(MainActivity.this, "Username is required!"); + } else if (TextUtils.isEmpty(password)) { + passwordInput.setError("Password is required!"); + showToast(MainActivity.this, "Password is required!"); + } else { + loginDialog.dismiss(); + showProgress(MainActivity.this); + passwordInput.setText(""); + final AuthThread thread = new AuthThread(username, password); + thread.start(); + } + } + }); + } + + private void setAuctionsView(ArrayList auctions) { + auctionsView = findViewById(R.id.auctionsView); + auctionsView.setAdapter(new AuctionAdapter(this, auctions)); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + auctionsView.setLayoutManager(linearLayoutManager); + } + + class AuctionThread extends SocketThread { + @Override + public void run() { + super.run(); + try { + sendMessage(new Packet(AUCTIONS, "").toJson()); + final Packet response = Packet.fromJson(in.readLine()); + close(); + Log.e("AUCTIONS", response.getData()); + runOnUiThread(new Runnable() { + @Override + public void run() { + setAuctionsView(response.toArrayList(Auction.class)); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + class AuthThread extends SocketThread { + String username; + String password; + + AuthThread(String username, String password) { + super(); + this.username = username; + this.password = password; + } + + @Override + public void run() { + super.run(); + try { + sendMessage(new Packet(USER, new User(username, password)).toJson()); + + final Packet packet = Packet.fromJson(in.readLine()); + Log.e("USER", packet.getData()); + int response = packet.toObject(Integer.class); + close(); + progressDialog.dismiss(); + if (response == -1) { + runOnUiThread(new Runnable() { + @Override + public void run() { + showToast(MainActivity.this, "Wrong password"); + loginDialog.show(); + } + }); + } else { + preferences.edit().putString("username", username).apply(); + preferences.edit().putInt("points", response).apply(); + BaseActivity.username = username; + BaseActivity.points = response; + showToast(MainActivity.this, "Welcome " + username); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Auction.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Auction.java new file mode 100644 index 0000000..35107d6 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Auction.java @@ -0,0 +1,82 @@ +package com.enescakir.auctioner.Model; + +import android.util.Log; + +import java.text.SimpleDateFormat; +import java.util.*; + +public class Auction { + private int id; + private String name; + private String description; + private int startPoint; + private String date; + + public Auction() { + } + + public Auction(int id, String name, String description, int startPoint, String date) { + this.id = id; + this.name = name; + this.description = description; + this.startPoint = startPoint; + this.date = date; + } + + public Auction(int id, String name, String description, String date) { + this.id = id; + this.name = name; + this.description = description; + this.date = date; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public int getStartPoint() { + return startPoint; + } + + public String getDate() { + return this.date; + } + + public Date getDateObject() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + return sdf.parse(this.getDate()); + } catch (Exception e) { + Log.e("Date Parsing", e.getMessage()); + } + return null; + } + + public String getHumanDate() { + SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy HH:mm"); + try { + return sdf.format(this.getDateObject()); + } catch (Exception e) { + Log.e("Date Parsing", e.getMessage()); + } + return null; + } + + public String getImageName() { + String filename = "auction[ID]"; + return filename.replace("[ID]", Integer.toString(this.id)); + } + + @Override + public String toString() { + return "Auction #" + Integer.toString(id) + ": " + name; + } +} diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Bid.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Bid.java new file mode 100644 index 0000000..0bce14d --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Bid.java @@ -0,0 +1,70 @@ +package com.enescakir.auctioner.Model; + +import android.util.Log; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +public class Bid { + private int point; + private String date; + private String username; + + public Bid(String username, int point, String date) { + this.point = point; + this.date = date; + this.username = username; + } + + public Bid(String username, int point, Date date) { + this.point = point; + this.username = username; + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + this.date = sdf.format(date); + } catch (Exception e) { + this.date = "2018-12-11 11:11:11"; + Log.e("Date Parsing", e.getMessage()); + } + + } + + public String getUsername() { + return username; + } + + public int getPoint() { + return point; + } + + public String getDate() { + return this.date; + } + + public Date getDateObject() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + return sdf.parse(this.getDate()); + } catch (Exception e) { + Log.e("Date Parsing", e.getMessage()); + } + return null; + } + + public String getHumanDate() { + SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy HH:mm:ss"); + try { + return sdf.format(this.getDateObject()); + } catch (Exception e) { + Log.e("Date Parsing", e.getMessage()); + } + return null; + } + + @Override + public String toString() { + return Integer.toString(point) + " bid on by " + username; + } +} diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Packet.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Packet.java new file mode 100644 index 0000000..e30a079 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/Packet.java @@ -0,0 +1,77 @@ +package com.enescakir.auctioner.Model; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +import java.util.ArrayList; +import java.util.List; + +public class Packet { + private Type type; + private String data; + + public enum Type { + UNKNOWN(0), // Unknown package + AUCTIONS(1), // Get auctions request, and return it + BID_LISTEN(2), // Subscribe client to auction bid channel + BID_NEW(3), // Broadcast new bid to clients + BID_STORE(4), // Store bid and return result + USER(5); // Store user and return save user result + + final int data; + + Type(int data) { + this.data = data; + } + } + + Packet(Type type, String data) { + this.type = type; + this.data = data; + } + + public Packet(Type type, Object data) { + this.type = type; + this.data = this.getJsonBuilder().toJson(data); + } + + public static Packet fromJson(String json) { + return getJsonBuilder().fromJson(json, Packet.class); + } + + public ArrayList toArrayList(Class clazz) { + return getArrayList(this.data, clazz); + } + + public T toObject(Class clazz) { + return getJsonBuilder().fromJson(this.data, clazz); + } + + public String toJson() { + return getJsonBuilder().toJson(this); + } + + public String getData() { + return data; + } + + public Type getType() { + return type; + } + + public static Gson getJsonBuilder() { + return new GsonBuilder().create(); + } + + public static ArrayList getArrayList(String rawJson, Class clazz) { + java.lang.reflect.Type type = TypeToken.getParameterized(List.class, clazz).getType(); + ArrayList data = getJsonBuilder().fromJson(rawJson, type); + + if (data != null) + return data; + + return new ArrayList<>(); + } + +} \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/SocketThread.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/SocketThread.java new file mode 100644 index 0000000..07ec598 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/SocketThread.java @@ -0,0 +1,51 @@ +package com.enescakir.auctioner.Model; + +import android.util.Log; + +import java.io.*; +import java.net.*; + +public class SocketThread extends Thread { + public Socket socket; + public BufferedReader in; + public BufferedWriter out; + + @Override + public void run() { + super.run(); + try { +// socket = new Socket("10.0.2.2", 5001); + socket = new Socket("18.224.60.222", 5001); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + } catch (Exception e) { + Log.e("SOCKET_THREAD", "Error"); + e.printStackTrace(); + } + } + + public void sendMessage(String message) { + Log.e("SEND_MESSAGE", message); + + try { + out.write(message); + out.newLine(); + out.flush(); + } catch (Exception e) { + Log.e("SEND_MESSAGE", "Error"); + e.printStackTrace(); + } + } + + public void close() { + try { + in.close(); + out.close(); + socket.close(); + this.interrupt(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/User.java b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/User.java new file mode 100644 index 0000000..0974846 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/java/com/enescakir/auctioner/Model/User.java @@ -0,0 +1,39 @@ +package com.enescakir.auctioner.Model; + +public class User { + private String name; + private String password; + private int point; + + public User(String name, String password) { + this.name = name; + this.password = password; + } + + public User(String name, String password, int point) { + this.name = name; + this.password = password; + this.point = point; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public int getPoint() { + return point; + } + + public void setPoint(int point) { + this.point = point; + } + + @Override + public String toString() { + return this.name + ":" + Integer.toString(this.point); + } +} \ No newline at end of file diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/cmpe436/final-project/Auctioner/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction1.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction1.png new file mode 100644 index 0000000..029c87b Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction1.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction10.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction10.png new file mode 100644 index 0000000..8c6797f Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction10.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction2.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction2.png new file mode 100644 index 0000000..bc7858e Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction2.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction3.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction3.png new file mode 100644 index 0000000..979e6f1 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction3.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction4.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction4.png new file mode 100644 index 0000000..8531c49 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction4.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction5.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction5.png new file mode 100644 index 0000000..15c84c9 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction5.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction6.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction6.png new file mode 100644 index 0000000..d863e41 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction6.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction7.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction7.png new file mode 100644 index 0000000..4e56de4 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction7.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction8.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction8.png new file mode 100644 index 0000000..7f120e3 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/auction8.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/ic_launcher_background.xml b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/drawable/ic_logout.png b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/ic_logout.png new file mode 100644 index 0000000..1ced963 Binary files /dev/null and b/cmpe436/final-project/Auctioner/app/src/main/res/drawable/ic_logout.png differ diff --git a/cmpe436/final-project/Auctioner/app/src/main/res/layout/activity_detail.xml b/cmpe436/final-project/Auctioner/app/src/main/res/layout/activity_detail.xml new file mode 100644 index 0000000..40285be --- /dev/null +++ b/cmpe436/final-project/Auctioner/app/src/main/res/layout/activity_detail.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + +