diff --git a/evlinkov/pom.xml b/evlinkov/pom.xml new file mode 100644 index 00000000..7de2e873 --- /dev/null +++ b/evlinkov/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + ru.fizteh.fivt.students + parent + 1.0-SNAPSHOT + + ru.fizteh.fivt.students + evlinkov + 1.0-SNAPSHOT + http://maven.apache.org + + UTF-8 + + + + org.twitter4j + twitter4j-stream + 4.0.4 + + + + com.beust + jcommander + 1.48 + + + + com.google.maps + google-maps-services + 0.1.7 + + + + com.google.code.geocoder-java + geocoder-java + 0.16 + + + antlr + antlr + 2.7.7 + + + org.json + json + 20151123 + + + junit + junit + 4.12 + test + + + \ No newline at end of file diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/BlockingQueue.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/BlockingQueue.java new file mode 100644 index 00000000..1726e38a --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/BlockingQueue.java @@ -0,0 +1,35 @@ +package ru.fizteh.fivt.students.evlinkov.threads; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +class BlockingQueue { + private int maxQueueSize; + private Queue elements; + BlockingQueue(int maxSize) { + maxQueueSize = maxSize; + elements = new LinkedList<>(); + } + public synchronized void offer(List e) throws InterruptedException { + while (elements.size() + e.size() > maxQueueSize) { + wait(); + } + for (int i = 0; i < e.size(); ++i) { + elements.add(e.get(i)); + } + notifyAll(); + } + public synchronized List take(int n) throws InterruptedException { + while (elements.size() < n) { + wait(); + } + List answer; + answer = new LinkedList<>(); + for (int i = 0; i < n; ++i) { + answer.add(elements.remove()); + } + notifyAll(); + return answer; + } +} diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/ThreadMuster.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/ThreadMuster.java new file mode 100644 index 00000000..4eec3ece --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/ThreadMuster.java @@ -0,0 +1,77 @@ +package ru.fizteh.fivt.students.evlinkov.threads; + +import java.util.Random; + +public class ThreadMuster { + public static class Runner { + private Random randNumber = new Random(); + private boolean ready = false; + private int printString = 1; + private int currentNumber = 0; + class AnswerQuestion extends Thread { + private volatile int numberOfThread; + AnswerQuestion(int number) { + numberOfThread = number + 1; + } + @Override + public void run() { + while (true) { + while (printString != numberOfThread) { + if (ready) { + return; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { } + } + int doit = randNumber.nextInt(10) + 1; + if (doit == 10) { + System.out.print("No\n"); + } else { + System.out.print("Yes\n"); + currentNumber++; + } + printString++; + } + } + } + void run(int n) { + System.out.print("Are you ready?\n"); + AnswerQuestion[] threads = new AnswerQuestion[n]; + for (int i = 0; i < n; ++i) { + threads[i] = new AnswerQuestion(i); + threads[i].start(); + } + while (true) { + if (printString == n + 1) { + if (currentNumber == n) { + ready = true; + break; + } else { + System.out.print("Are you ready?\n"); + currentNumber = 0; + printString = 1; + } + } else { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { } + } + } + for (int i = 0; i < n; ++i) { + try { + threads[i].join(); + } catch (InterruptedException e) { } + } + } + } + public static void main(String[] args) { + int n; + if (args.length > 0) { + n = Integer.parseInt(args[0]); + } else { + n = 0; + } + new Runner().run(n); + } +} diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/ThreadRhymes.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/ThreadRhymes.java new file mode 100644 index 00000000..7635de8b --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/threads/ThreadRhymes.java @@ -0,0 +1,50 @@ +package ru.fizteh.fivt.students.evlinkov.threads; + +public class ThreadRhymes { + public static class Runner { + private int currentNumber = 1; + class PutsThread extends Thread { + private volatile int numberOfThread; + PutsThread(int number) { + numberOfThread = number + 1; + } + @Override + public void run() { + while (true) { + while (currentNumber != numberOfThread) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { } + } + System.out.print("Thread-" + numberOfThread + "\n"); + currentNumber++; + } + } + } + void run(int n) { + PutsThread[] threads = new PutsThread[n]; + for (int i = 0; i < n; ++i) { + threads[i] = new PutsThread(i); + threads[i].start(); + } + while (true) { + if (currentNumber == n + 1) { + currentNumber = 1; + } else { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { } + } + } + } + } + public static void main(String[] args) { + int n; + if (args.length > 0) { + n = Integer.parseInt(args[0]); + } else { + n = 0; + } + new Runner().run(n); + } +} diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Location.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Location.java new file mode 100644 index 00000000..a4e02ffd --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Location.java @@ -0,0 +1,64 @@ +package ru.fizteh.fivt.students.evlinkov.twitterstream; +/** + * Created by evlinkov on 17.12.15. + */ +import com.google.maps.model.GeocodingResult; +import com.google.maps.GeoApiContext; +import com.google.maps.GeocodingApi; +import com.google.maps.model.Bounds; +import com.google.maps.model.LatLng; + +import java.io.FileNotFoundException; +import java.io.FileInputStream; +import static java.lang.Math.*; +import java.util.Properties; +import java.io.IOException; +import java.io.InputStream; + +public class Location { + private static final double RADIUS_OF_THE_EARTH = 6371; + private GeocodingResult result; + private double radius; + Location(String place) throws Exception { + if (!place.equals("nearby")) { + String apiKey = getKeyFromProperties(); + GeoApiContext context = new GeoApiContext().setApiKey(apiKey); + result = GeocodingApi.geocode(context, place).await()[0]; + radius = calculateRadius(); + } + } + private String getKeyFromProperties() throws IOException { + Properties property = new Properties(); + try (InputStream input = new FileInputStream("twitter4j.properties")) { + property.load(input); + } catch (FileNotFoundException e) { + System.err.println("Not found the file : " + e.getMessage()); + throw e; + } catch (IOException e) { + System.err.println("Not read the file : " + e.getMessage()); + throw e; + } + return property.getProperty("googleApiKey"); + } + public LatLng getLocation() { + return result.geometry.location; + } + public double getRadius() { + return radius; + } + private double calculateRadius() { + LatLng pointerFirst = result.geometry.bounds.northeast; + LatLng pointerSecond = result.geometry.bounds.southwest; + double rad = 180.0 / PI; + double x = cos(pointerFirst.lat / rad) * cos(pointerFirst.lng / rad) * cos(pointerSecond.lat / rad) + * cos(pointerSecond.lng / rad); + double y = cos(pointerFirst.lat / rad) * sin(pointerFirst.lng / rad) * cos(pointerSecond.lat / rad) + * sin(pointerSecond.lng / rad); + double z = sin(pointerFirst.lat / rad) * sin(pointerSecond.lat / rad); + + return RADIUS_OF_THE_EARTH * acos(x + y + z); + } + public final Bounds getBounds() { + return result.geometry.bounds; + } +} diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Parameters.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Parameters.java new file mode 100644 index 00000000..a225bbe4 --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Parameters.java @@ -0,0 +1,45 @@ +package ru.fizteh.fivt.students.evlinkov.twitterstream; +/** + * Created by evlinkov on 17.12.15. + */ +import com.beust.jcommander.Parameter; + +public class Parameters { + static final int USUAL_TWEETS_LIMIT = 555; + @Parameter(names = {"--query", "-q"}, + description = "Search query") + private String query = ""; + @Parameter(names = {"--place", "-p"}, + description = "Search place") + private String place = ""; + @Parameter(names = {"--stream", "-s"}, + description = "Stream mode") + private boolean stream = false; + @Parameter(names = {"--hideRetweets"}, + description = "Hide retweets") + private boolean hideRetweets = false; + @Parameter(names = {"--limit", "-l"}, + description = "Limit tweets") + private int limitTweets = USUAL_TWEETS_LIMIT; + @Parameter(names = {"--help", "-h"}, + description = "Help mode") + private boolean helpMode = false; + public String getQuery() { + return query; + } + public String getPlace() { + return place; + } + public boolean checkStream() { + return stream; + } + public boolean checkHideRetweets() { + return hideRetweets; + } + public int getLimitTweets() { + return limitTweets; + } + public boolean checkHelpMode() { + return helpMode; + } +} diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Time.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Time.java new file mode 100644 index 00000000..ea5865fc --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/Time.java @@ -0,0 +1,37 @@ +package ru.fizteh.fivt.students.evlinkov.twitterstream; +/** + * Created by evlinkov on 17.12.15. + */ +import java.time.temporal.ChronoUnit; +import java.time.ZoneId; +import java.util.Date; +import java.time.*; + +public class Time { + public static String printTime(long tweetTime, long currentTime) { + LocalDateTime currentTimer = new Date(currentTime).toInstant() + .atZone(ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime tweetTimer = new Date(tweetTime).toInstant() + .atZone(ZoneId.systemDefault()).toLocalDateTime(); + if (tweetTimer.isAfter(currentTimer.minusMinutes(2))) { + return "Только что"; + } else { + if (tweetTimer.isAfter(currentTimer.minusHours(1))) { + return new StringBuilder().append(ChronoUnit.MINUTES.between(tweetTimer, currentTimer)) + .append(" минут назад").toString(); + } else { + if (currentTimer.toLocalDate().isEqual(tweetTimer.toLocalDate())) { + return new StringBuilder().append(ChronoUnit.HOURS.between(tweetTimer, currentTimer)) + .append(" часов назад").toString(); + } else { + if (tweetTimer.toLocalDate().isEqual(currentTimer.minusDays(1).toLocalDate())) { + return "вчера"; + } else { + return new StringBuilder().append(ChronoUnit.DAYS.between(tweetTimer, currentTimer)) + .append(" дней назад").toString(); + } + } + } + } + } +} diff --git a/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TwitterStream.java b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TwitterStream.java new file mode 100644 index 00000000..5ce6883d --- /dev/null +++ b/evlinkov/src/main/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TwitterStream.java @@ -0,0 +1,139 @@ +package ru.fizteh.fivt.students.evlinkov.twitterstream; +/** + * Created by evlinkov on 17.12.15. + */ +import com.beust.jcommander.JCommander; +import twitter4j.*; + +import java.util.List; + +public class TwitterStream { + public static final long PAUSE = 1000; + public static void main(String[] args) throws Exception { + Parameters parameters = new Parameters(); + JCommander jCommander; + try { + jCommander = new JCommander(parameters, args); + } catch (Exception ex) { + jCommander = new JCommander(parameters, new String[] {"-h"}); //ok, if args is wrong, let's show HelpMode + jCommander.usage(); + return; + } + if (parameters.checkHelpMode()) { + jCommander.usage(); + return; + } + if (parameters.checkStream()) { + streamPrint(parameters); + } else { + print(parameters); + } + } + public static void printTime(Status status) { + Time printer = new Time(); + System.out.print(new StringBuilder().append("[") + .append(printer.printTime(status.getCreatedAt().getTime(), System.currentTimeMillis())).append("]")); + } + public static void printRetweetsCount(Status status) { + System.out.println(new StringBuilder().append("(").append(status.getRetweetCount()) + .append(" ретвитов)").toString()); + } + public static void printTweet(Status status) { + System.out.print(new StringBuilder().append("@").append(status.getUser().getName()).append(": ") + .append(status.getText())); + } + public static void printRetweet(Status status) { + System.out.println(new StringBuilder().append("@").append(status.getUser().getName()) + .append(" ретвитнул: @").append(status.getRetweetedStatus().getUser().getName()).append(": ") + .append(status.getRetweetedStatus().getText()).toString()); + System.out.println(); + } + public static void print(Parameters parameters) { + Twitter twitter = new TwitterFactory().getInstance(); + try { + Query query = new Query(parameters.getQuery()); + if (!parameters.getPlace().equals("")) { + if (!parameters.getPlace().equals("nearby")) { + Location googleFindPlace; + googleFindPlace = new Location(parameters.getPlace()); + GeoLocation geoLocation; + geoLocation = new GeoLocation(googleFindPlace.getLocation().lat, googleFindPlace.getLocation().lng); + query.setGeoCode(geoLocation, googleFindPlace.getRadius(), Query.KILOMETERS); + } + } + query.setCount(parameters.getLimitTweets()); + QueryResult answer; + answer = twitter.search(query); + List tweets = answer.getTweets(); + if (tweets.isEmpty()) { + System.out.println("Nothing find"); + return; + } + for (Status tweet : tweets) { + Thread.sleep(PAUSE); + if (!tweet.isRetweet()) { + printTime(tweet); + printTweet(tweet); + printRetweetsCount(tweet); + System.out.println(); + } else { + if (!parameters.checkHideRetweets()) { + printTime(tweet); + printRetweet(tweet); + } + } + } + } catch (TwitterException te) { + te.printStackTrace(); + System.err.println("Failed to search tweets: " + te.getMessage()); + System.exit(1); + } catch (InterruptedException e) { + e.printStackTrace(); + System.err.println(e.getMessage()); + System.exit(1); + } catch (Exception e) { + e.printStackTrace(); + } + } + public static void streamPrint(Parameters parameters) throws Exception { + twitter4j.TwitterStream twitterStream; + twitterStream = new TwitterStreamFactory().getInstance(); + StatusAdapter listener = new StatusAdapter() { + @Override + public void onStatus(Status status) { + try { + Thread.sleep(PAUSE); + } catch (InterruptedException e) { + System.out.print(e.getMessage()); + } + if (!status.isRetweet()) { + printTweet(status); + System.out.println(); + } else { + if (!parameters.checkHideRetweets()) { + printRetweet(status); + } + } + } + }; + twitterStream.addListener(listener); + if (parameters.getQuery() == "" && parameters.getPlace() == "") { + twitterStream.sample(); + } else { + FilterQuery filter; + String[] track = new String[1]; + track[0] = parameters.getQuery(); + filter = new FilterQuery(0, new long[0], track); + if (!parameters.getPlace().equals("")) { + Location findPlace; + findPlace = new Location((parameters.getPlace())); + double[][] bounds = {{findPlace.getBounds().southwest.lng, + findPlace.getBounds().southwest.lat}, + {findPlace.getBounds().northeast.lng, + findPlace.getBounds().northeast.lat}}; + filter.locations(bounds); + } + twitterStream.filter(filter); + } + } +} diff --git a/evlinkov/src/test/java/ru/fizteh/fivt/students/AppTest.java b/evlinkov/src/test/java/ru/fizteh/fivt/students/AppTest.java new file mode 100644 index 00000000..a5e295f7 --- /dev/null +++ b/evlinkov/src/test/java/ru/fizteh/fivt/students/AppTest.java @@ -0,0 +1,38 @@ +package ru.fizteh.fivt.students; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest +extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} \ No newline at end of file diff --git a/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/threads/BlockingQueueModuleTest.java b/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/threads/BlockingQueueModuleTest.java new file mode 100644 index 00000000..1af56428 --- /dev/null +++ b/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/threads/BlockingQueueModuleTest.java @@ -0,0 +1,49 @@ +package ru.fizteh.fivt.students.evlinkov.threads; + +import java.util.LinkedList; +import java.util.List; + +public class BlockingQueueModuleTest { + private static BlockingQueue queue = new BlockingQueue(10); + static class TestOffer implements Runnable { + private List elements = new LinkedList(); + TestOffer(int numberOfElements) { + for (int i = 0; i < numberOfElements; ++i) { + elements.add(i); + } + } + @Override + public void run() { + try { + queue.offer(elements); + System.out.print("Offer\n"); + } catch (InterruptedException e) { } + } + } + static class TestTake implements Runnable { + private List elements; + private int numberOfElements; + TestTake(int number) { + numberOfElements = number; + } + @Override + public void run() { + try { + elements = queue.take(numberOfElements); + System.out.print("Take :"); + for (int i = 0; i < elements.size(); ++i) { + System.out.print(" " + elements.get(i)); + } + System.out.print("\n"); + } catch (InterruptedException e) { } + } + } + public static void main(String[] args) { + new Thread(new TestOffer(5)).start(); + new Thread(new TestOffer(3)).start(); + new Thread(new TestOffer(3)).start(); + new Thread(new TestTake(3)).start(); + new Thread(new TestTake(9)).start(); + new Thread(new TestOffer(2)).start(); + } +} diff --git a/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TestParameters.java b/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TestParameters.java new file mode 100644 index 00000000..e39da03e --- /dev/null +++ b/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TestParameters.java @@ -0,0 +1,53 @@ +package ru.fizteh.fivt.students.evlinkov.twitterstream; +/** + * Created by evlinkov on 17.12.15. + */ +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import org.junit.Assert; +import org.junit.Test; + +public class TestParameters { + @Test + public void testHelp() { + Parameters commandLine = new Parameters(); + new JCommander(commandLine, new String[]{"-h"}); + Assert.assertEquals(true, commandLine.checkHelpMode()); + } + @Test + public void testStream() { + Parameters commandLine = new Parameters(); + new JCommander(commandLine, new String[]{"--stream"}); + Assert.assertEquals(true, commandLine.checkStream()); + Assert.assertEquals(false, commandLine.checkHideRetweets()); + } + @Test + public void testPlace() { + Parameters commandLine = new Parameters(); + new JCommander(commandLine, new String[]{"--place", "Volgograd"}); + Assert.assertEquals("Volgograd", commandLine.getPlace()); + Assert.assertEquals(555, commandLine.getLimitTweets()); + } + @Test + public void testQuery() { + Parameters commandLine = new Parameters(); + new JCommander(commandLine, new String[]{"--query", "Luntiki", "--help"}); + Assert.assertEquals("Luntiki", commandLine.getQuery()); + Assert.assertEquals(true, commandLine.checkHelpMode()); + Assert.assertEquals("", commandLine.getPlace()); + } + @Test + public void testHideRetweets() { + Parameters commandLine = new Parameters(); + new JCommander(commandLine, new String[]{"--hideRetweets"}); + Assert.assertEquals("", commandLine.getQuery()); + Assert.assertEquals(true, commandLine.checkHideRetweets()); + } + @Test + public void testLimitTweets() { + Parameters commandLine = new Parameters(); + new JCommander(commandLine, new String[]{"--limit", "230"}); + Assert.assertEquals(false, commandLine.checkHelpMode()); + Assert.assertEquals(230, commandLine.getLimitTweets()); + } +} diff --git a/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TestTime.java b/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TestTime.java new file mode 100644 index 00000000..972e8c16 --- /dev/null +++ b/evlinkov/src/test/java/ru/fizteh/fivt/students/evlinkov/twitterstream/TestTime.java @@ -0,0 +1,39 @@ +package ru.fizteh.fivt.students.evlinkov.twitterstream; +/** + * Created by evlinkov on 17.12.15. + */ +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.Month; + +import org.junit.Assert; +import org.junit.Test; + +public class TestTime { + @Test + public void test() { + long start = LocalDate.of(2015, Month.JANUARY, 1) + .atTime(0, 0, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + long finish = LocalDate.of(2015, Month.JANUARY, 1) + .atTime(0, 0, 1) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + Assert.assertEquals("Только что", Time.printTime(start, finish)); + finish = LocalDate.of(2015, Month.JANUARY, 1) + .atTime(0, 15, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + Assert.assertEquals("15 минут назад", Time.printTime(start, finish)); + finish = LocalDate.of(2015, Month.JANUARY, 1) + .atTime(5, 0, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + Assert.assertEquals("5 часов назад", Time.printTime(start, finish)); + finish = LocalDate.of(2015, Month.JANUARY, 2) + .atTime(0, 1, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + Assert.assertEquals("вчера", Time.printTime(start, finish)); + finish = LocalDate.of(2015, Month.JANUARY, 4) + .atTime(3, 20, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + Assert.assertEquals("3 дней назад", Time.printTime(start, finish)); + } +} diff --git a/pom.xml b/pom.xml index a2fdfbd2..50a58382 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,7 @@ preidman Jettriangle nmakeenkov + evlinkov oshch ladyae