From 2d78b3b89fbf660f642f423a9c48a8131ea90e3f Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Thu, 31 Jul 2014 13:16:29 +0200 Subject: [PATCH] Add filter for retrieving the Savoy theatre movie programme. --- .../filters/webpages/SavoyTicketsFilter.java | 129 ++ .../rhynodge/filters/webpages/savoy/Movie.java | 44 + .../filters/webpages/savoy/MovieExtractor.java | 93 ++ .../filters/webpages/savoy/TicketLink.java | 31 + .../rhynodge/watchers/SavoyTicketWatcher.java | 29 + .../filters/webpages/savoy/MovieExtractorTest.java | 105 ++ .../rhynodge/filters/webpages/savoy/savoy.html | 1552 ++++++++++++++++++++ 7 files changed, 1983 insertions(+) create mode 100644 src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java create mode 100644 src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java create mode 100644 src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.java create mode 100644 src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/TicketLink.java create mode 100644 src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java create mode 100644 src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java create mode 100644 src/test/resources/net/pterodactylus/rhynodge/filters/webpages/savoy/savoy.html diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java new file mode 100644 index 0000000..d62529e --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java @@ -0,0 +1,129 @@ +package net.pterodactylus.rhynodge.filters.webpages; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.time.format.DateTimeFormatter.ofPattern; +import static java.util.Optional.empty; +import static java.util.Optional.of; +import static net.pterodactylus.rhynodge.filters.webpages.savoy.Movie.byName; +import static net.pterodactylus.rhynodge.filters.webpages.savoy.Movie.withPresentations; +import static net.pterodactylus.rhynodge.filters.webpages.savoy.TicketLink.byPresentationTime; +import static org.jsoup.nodes.Document.createShell; +import static org.jsoup.parser.Tag.valueOf; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import net.pterodactylus.rhynodge.Filter; +import net.pterodactylus.rhynodge.State; +import net.pterodactylus.rhynodge.filters.webpages.savoy.Movie; +import net.pterodactylus.rhynodge.filters.webpages.savoy.MovieExtractor; +import net.pterodactylus.rhynodge.filters.webpages.savoy.TicketLink; +import net.pterodactylus.rhynodge.states.HtmlState; +import net.pterodactylus.rhynodge.states.OutputState; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; + +/** + * {@link Filter} implementation that creates a list of movies running at the + * Savoy theatre in Hamburg. + * + * @author David ‘Bombe’ Roden + */ +public class SavoyTicketsFilter implements Filter { + + private static final MovieExtractor movieExtractor = new MovieExtractor(); + private DateTimeFormatter dateFormatter = ofPattern("dd.MM.uuuu"); + private DateTimeFormatter timeFormatter = ofPattern("HH:mm"); + private DateTimeFormatter dateTimeFormatter = ofPattern("dd.MM.uuuu, HH:mm"); + + @Override + public State filter(State state) { + checkArgument(state instanceof HtmlState, "state must be HTML"); + + HtmlState htmlState = (HtmlState) state; + Collection movies = movieExtractor.getMovies(htmlState.document()); + return new OutputState(getPlainTextOutput(movies), getHtmlOutput(movies)); + } + + private Optional getHtmlOutput(Collection movies) { + Document document = createShell(""); + document.head().appendElement("style").attr("type", "text/css").text(generateStyleSheet()); + document.body().appendElement("h1").text("Kinoprogramm: Savoy"); + document.body().appendElement("h2").text("Filme"); + movies.stream().filter(withPresentations).sorted(byName).forEach(movie -> { + document.body().appendChild(createMovieNode(movie)); + }); + document.body().appendElement("h2").text("Zeiten"); + movies.stream().flatMap(movie -> movie.getTicketLinks().stream().map(ticketLink -> new Presentation(movie, ticketLink))).sorted((leftPresentation, rightPresentation) -> leftPresentation.getTicketLink().getPresentationTime().compareTo(rightPresentation.getTicketLink().getPresentationTime())).collect(Collectors.groupingBy(presentation -> presentation.getTicketLink().getPresentationTime().toLocalDate())).entrySet().stream().sorted((leftEntry, rightEntry) -> leftEntry.getKey().compareTo(rightEntry.getKey())).forEach(dateEntry -> { + document.body().appendChild(createDayNode(dateEntry.getKey(), dateEntry.getValue())); + }); + document.body().appendElement("h2").text("Vorschau"); + movies.stream().filter(withPresentations.negate()).sorted(byName).forEach(movie -> { + document.body().appendElement("div").attr("class", "name").text(movie.getName()); + }); + return of(document.toString()); + } + + private String generateStyleSheet() { + StringBuilder styleSheet = new StringBuilder(); + styleSheet.append(".movie .name { font-weight: bold; }\n"); + styleSheet.append(".day:first-child { margin-top: 1em; }\n"); + styleSheet.append(".date { display: table-cell; font-weight: bold; }\n"); + styleSheet.append(".presentation { display: inline; }\n"); + styleSheet.append(".time, .movie { display: inline; }\n"); + return styleSheet.toString(); + } + + private Node createMovieNode(Movie movie) { + Element movieNode = new Element(valueOf("div"), ""); + movieNode.attr("class", "movie"); + movieNode.appendElement("div").attr("class", "name").text(movie.getName()); + movie.getTicketLinks().stream().sorted(byPresentationTime).forEach(ticketLink -> { + Element presentationNode = movieNode.appendElement("div").attr("class", "presentation"); + presentationNode.appendElement("div").attr("class", "time").text("» ").appendElement("a").attr("href", ticketLink.getLink()).text(ticketLink.getPresentationTime().format(dateTimeFormatter)); + }); + return movieNode; + } + + private Node createDayNode(LocalDate date, List presentations) { + Element dayNode = new Element(valueOf("div"), "").attr("class", "day"); + dayNode.appendElement("div").attr("class", "date").text(date.format(dateFormatter)); + presentations.stream().forEach(presentation -> { + Element presentationNode = dayNode.appendElement("div").attr("class", "presentation"); + presentationNode.appendElement("div").attr("class", "time").text("» " + presentation.getTicketLink().getPresentationTime().format(timeFormatter)); + presentationNode.appendElement("div").attr("class", "movie").appendElement("a").attr("href", presentation.getTicketLink().getLink()).text(presentation.getMovie().getName()); + }); + return dayNode; + } + + private Optional getPlainTextOutput(Collection movies) { + return empty(); + } + + private static class Presentation { + + private final Movie movie; + private final TicketLink ticketLink; + + private Presentation(Movie movie, TicketLink ticketLink) { + this.movie = movie; + this.ticketLink = ticketLink; + } + + private Movie getMovie() { + return movie; + } + + private TicketLink getTicketLink() { + return ticketLink; + } + + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java new file mode 100644 index 0000000..e3b8844 --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java @@ -0,0 +1,44 @@ +package net.pterodactylus.rhynodge.filters.webpages.savoy; + +import static java.lang.String.format; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.function.Predicate; + +/** + * Information about a movie. + * + * @author David ‘Bombe’ Roden + */ +public class Movie { + + private final String name; + private final List ticketLinks = new ArrayList<>(); + + public static final Predicate withPresentations = movie -> !movie.getTicketLinks().isEmpty(); + public static final Comparator byName = (leftMovie, rightMovie) -> leftMovie.getName().compareToIgnoreCase(rightMovie.getName()); + + public Movie(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List getTicketLinks() { + return ticketLinks; + } + + public void addTicketLink(TicketLink ticketLink) { + ticketLinks.add(ticketLink); + } + + @Override + public String toString() { + return format("%s (%d)", name, ticketLinks.size()); + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.java b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.java new file mode 100644 index 0000000..ae7d072 --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.java @@ -0,0 +1,93 @@ +package net.pterodactylus.rhynodge.filters.webpages.savoy; + +import static java.time.format.DateTimeFormatter.ofPattern; +import static java.util.Optional.empty; +import static java.util.Optional.of; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +/** + * Extracts {@link Movie} information from an HTML document. + * + * @author David ‘Bombe’ Roden + */ +public class MovieExtractor { + + private static final Pattern datePattern = Pattern.compile(".*([0-9]{2}\\.[0-9]{2}\\.[0-9]{2}).*"); + private static final Pattern timePattern = Pattern.compile(".*([0-9]{2}:[0-9]{2}).*"); + private static final DateTimeFormatter dateFormatter = ofPattern("dd.MM.uu"); + private static final DateTimeFormatter timeFormatter = ofPattern("HH:mm"); + + public Set getMovies(Document document) { + Set movies = new HashSet<>(); + for (Element movieElement : document.select(".tx-spmovies-pi1-listrow")) { + String name = movieElement.select(".tx-spmovies-pi1-header h1").text(); + Movie movie = new Movie(name); + for (TicketLink ticketLink : extractTicketLinks(movieElement)) { + movie.addTicketLink(ticketLink); + } + movies.add(movie); + } + return movies; + } + + private Iterable extractTicketLinks(Element movieElement) { + Set ticketLinks = new HashSet<>(); + int dateCellIndex = 1; + for (Element dateCell : movieElement.select(".tx-spmovies-pi1-date-column")) { + Optional dateString = extractDateString(dateCell); + if (!dateString.isPresent()) { + continue; + } + for (Element timeCell : getTimeCells(movieElement, dateCellIndex++)) { + Optional timeString = extractTimeString(timeCell.select("a").text()); + if (!timeString.isPresent()) { + continue; + } + LocalDateTime localDateTime = getPresentationTime(dateString, timeString); + String link = timeCell.select("a").attr("href"); + TicketLink ticketLink = new TicketLink(localDateTime, link); + ticketLinks.add(ticketLink); + } + } + return ticketLinks; + } + + private LocalDateTime getPresentationTime(Optional dateString, Optional timeString) { + LocalDate date = LocalDate.parse(dateString.get(), dateFormatter); + LocalTime localTime = LocalTime.parse(timeString.get(), timeFormatter); + return date.atTime(localTime); + } + + private Optional extractTimeString(String cellContent) { + Matcher timeMatcher = timePattern.matcher(cellContent); + if (!timeMatcher.matches() || timeMatcher.groupCount() < 1) { + return empty(); + } + return of(timeMatcher.group(1)); + } + + private Iterable getTimeCells(Element movieElement, int dateCellIndex) { + return movieElement.select(".tx-spmovies-pi1-shows:eq(" + dateCellIndex + ") div.time"); + } + + private Optional extractDateString(Element dateCell) { + Matcher matcher = datePattern.matcher(dateCell.text()); + if (!matcher.matches() || matcher.groupCount() < 1) { + return empty(); + } + return of(matcher.group(1)); + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/TicketLink.java b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/TicketLink.java new file mode 100644 index 0000000..357245f --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/TicketLink.java @@ -0,0 +1,31 @@ +package net.pterodactylus.rhynodge.filters.webpages.savoy; + +import java.time.LocalDateTime; +import java.util.Comparator; + +/** + * Information about a presentation and a link to buy a ticket. + * + * @author David ‘Bombe’ Roden + */ +public class TicketLink { + + private final LocalDateTime presentationTime; + private final String ticketLink; + + public static final Comparator byPresentationTime = (leftTicketLink, rightTicketLink) -> leftTicketLink.getPresentationTime().compareTo(rightTicketLink.getPresentationTime()); + + public TicketLink(LocalDateTime presentationTime, String ticketLink) { + this.presentationTime = presentationTime; + this.ticketLink = ticketLink; + } + + public LocalDateTime getPresentationTime() { + return presentationTime; + } + + public String getLink() { + return ticketLink; + } + +} diff --git a/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java b/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java new file mode 100644 index 0000000..199d3ec --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/watchers/SavoyTicketWatcher.java @@ -0,0 +1,29 @@ +package net.pterodactylus.rhynodge.watchers; + +import static java.util.Arrays.asList; + +import net.pterodactylus.rhynodge.Watcher; +import net.pterodactylus.rhynodge.filters.HtmlFilter; +import net.pterodactylus.rhynodge.filters.webpages.SavoyTicketsFilter; +import net.pterodactylus.rhynodge.queries.HttpQuery; +import net.pterodactylus.rhynodge.triggers.AlwaysTrigger; + +/** + * {@link Watcher} implementation that shows tickets sold in the Savoy theatre. + * + * @author David ‘Bombe’ Roden + */ +public class SavoyTicketWatcher extends DefaultWatcher { + + public SavoyTicketWatcher() { + super( + new HttpQuery("http://www.savoy-filmtheater.de/filmprogramm.html"), + asList( + new HtmlFilter(), + new SavoyTicketsFilter() + ), + new AlwaysTrigger() + ); + } + +} diff --git a/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java b/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java new file mode 100644 index 0000000..d1e9dc8 --- /dev/null +++ b/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java @@ -0,0 +1,105 @@ +package net.pterodactylus.rhynodge.filters.webpages.savoy; + +import static java.time.LocalDateTime.of; +import static java.util.Optional.empty; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.notNullValue; +import static org.jsoup.Jsoup.parse; + +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.jsoup.nodes.Document; +import org.junit.Test; + +/** + * Unit test for {@link MovieExtractor}. + * + * @author David ‘Bombe’ Roden + */ +public class MovieExtractorTest { + + private final Document document; + private final MovieExtractor movieExtractor = new MovieExtractor(); + private Collection movies; + + public MovieExtractorTest() throws IOException { + document = loadDocument("savoy.html", "http://foo"); + movies = movieExtractor.getMovies(document); + } + + private Document loadDocument(String resourceName, String baseUri) throws IOException { + InputStream inputStream = getClass().getResourceAsStream(resourceName); + return parse(inputStream, "UTF-8", baseUri); + } + + @Test + public void moviesAreLocated() throws IOException { + assertThat(movies, notNullValue()); + assertThat(movies, containsInAnyOrder( + movie("22 Jump Street (OV)", of(2014, 7, 30, 20, 15), of(2014, 7, 31, 20, 15), of(2014, 8, 1, 22, 30), of(2014, 8, 2, 20, 0), of(2014, 8, 2, 22, 45), of(2014, 8, 3, 17, 30), of(2014, 8, 4, 17, 30), of(2014, 8, 5, 20, 0)), + movie("How to Train Your Dragon 2 (3D/OV)", of(2014, 7, 30, 17, 45), of(2014, 8, 1, 14, 15), of(2014, 8, 2, 17, 30), of(2014, 8, 3, 15, 0), of(2014, 8, 4, 20, 0)), + movie("Jersey Boys (OV)", of(2014, 7, 31, 17, 15), of(2014, 8, 1, 16, 30), of(2014, 8, 3, 20, 0), of(2014, 8, 5, 17, 0)), + movie("FILM CLUB presents: Ghostbusters (OV)", of(2014, 8, 1, 19, 30)), + movie("Transformers: Age of Extinction (3D/OV)", of(2014, 8, 2, 14, 0)), + movie("Dawn of the Planet of the Apes (3D/OV)"), + movie("Traumkino: Yves Saint Laurent (Deutsche Fassung)"), + movie("Hector and the Search for Happiness (OV)"), + movie("The Expendables 3 (OV)"), + movie("Doctor Who: Deep Breath"), + movie("Traumkino: Boyhood (Deutsche Sprachfassung)") + )); + } + + private Matcher movie(String name, LocalDateTime... presentationTimes) { + return new TypeSafeDiagnosingMatcher() { + @Override + protected boolean matchesSafely(Movie movie, Description mismatchDescription) { + if (!movie.getName().equals(name)) { + mismatchDescription.appendText("movie is named ").appendValue(movie.getName()); + return false; + } + List ticketLinks = new ArrayList<>(movie.getTicketLinks()); + if (ticketLinks.size() != presentationTimes.length) { + mismatchDescription.appendText("has ").appendValue(ticketLinks.size()).appendText(" presentations"); + return false; + } + for (LocalDateTime presentationTime : presentationTimes) { + Optional foundTicketLink = empty(); + for (TicketLink ticketLink : ticketLinks) { + if (ticketLink.getPresentationTime().equals(presentationTime)) { + foundTicketLink = Optional.of(ticketLink); + break; + } + } + if (!foundTicketLink.isPresent()) { + mismatchDescription.appendValue("has no presentation at ").appendValue(presentationTime); + return false; + } + ticketLinks.remove(foundTicketLink.get()); + } + if (!ticketLinks.isEmpty()) { + mismatchDescription.appendText("has no presentations at ").appendValueList("", ", ", "", ticketLinks); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("movie with name ").appendValue(name); + description.appendText(" and ").appendValue(presentationTimes.length).appendText(" presentations"); + } + }; + } + +} diff --git a/src/test/resources/net/pterodactylus/rhynodge/filters/webpages/savoy/savoy.html b/src/test/resources/net/pterodactylus/rhynodge/filters/webpages/savoy/savoy.html new file mode 100644 index 0000000..84dbe56 --- /dev/null +++ b/src/test/resources/net/pterodactylus/rhynodge/filters/webpages/savoy/savoy.html @@ -0,0 +1,1552 @@ + + + + + + + + + + +Filmprogramm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + + +
+ + + + + +
+ +
+ + + + + + + + + + + +
+ + + Foto: 22 Jump Street (OV) + + +   +

22 Jump Street (OV)

+

Action | Comedy | Crime - USA 2014
+FSK: 12 - 112 minutes
+
+Preview: July 30 at 8.15 pm
+Director: Phil Lord, Christopher Miller
+Stars: Jonah Hill, Channing Tatum, Ice Cube, Nick Offerman, Jack Maloney

+

ab 30.07.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Saal + + Heute + +
+ 30.07.14
+ + Do + +
+ 31.07.14
+ + Fr + +
+ 01.08.14
+ + Sa + +
+ 02.08.14
+ + So + +
+ 03.08.14
+ + Mo + +
+ 04.08.14
+ + Di + +
+ 05.08.14
Saal
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: How to Train Your Dragon 2 (3D/OV) + + +   +

How to Train Your Dragon 2 (3D/OV)

+

Animation | Action| Adventure - USA 2014
+FSK: 6 - 102 minutes
+
+Director: Dean DeBlois
+Stars: Cate Blanchett, Gerard Butler, Jonah Hill, Kristen Wiig, Craig Ferguson
+

+

ab 24.07.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offzielle Webseite zum Film!

+ + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Saal + + Heute + +
+ 30.07.14
+ + Do + +
+ 31.07.14
+ + Fr + +
+ 01.08.14
+ + Sa + +
+ 02.08.14
+ + So + +
+ 03.08.14
+ + Mo + +
+ 04.08.14
+ + Di + +
+ 05.08.14
Saal
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Jersey Boys (OV) + + +   +

Jersey Boys (OV)

+

Biography | Drama | Musical - USA 2014
+FSK: 6 - 134 minutes
+
+Director: Clint Eastwood - Stars: Vincent Piazza, John Lloyd Young, Steve Schirripa, Christopher Walken, Kathrine Narducci

+

ab 31.07.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Saal + + Heute + +
+ 30.07.14
+ + Do + +
+ 31.07.14
+ + Fr + +
+ 01.08.14
+ + Sa + +
+ 02.08.14
+ + So + +
+ 03.08.14
+ + Mo + +
+ 04.08.14
+ + Di + +
+ 05.08.14
Saal
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: FILM CLUB presents: Ghostbusters (OV) + + +   +

FILM CLUB presents: Ghostbusters (OV)

+

Comedy | Fantasy | Sci-Fi - USA 1984
+FSK: 12 - 105 minutes
+
+Friday, August 1 at 7.30pm
+
+Director: Ivan Reitman - Stars: Bill Murray, Dan Aykroyd, Harold Ramis, Sigourney Weaver, Rick Moranis

+

01.08. bis 01.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Saal + + Heute + +
+ 30.07.14
+ + Do + +
+ 31.07.14
+ + Fr + +
+ 01.08.14
+ + Sa + +
+ 02.08.14
+ + So + +
+ 03.08.14
+ + Mo + +
+ 04.08.14
+ + Di + +
+ 05.08.14
Saal
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Transformers: Age of Extinction (3D/OV) + + +   +

Transformers: Age of Extinction (3D/OV)

+

Action | Adventure | Sci-Fi - USA 2014
+FSK: 12 - 165 minutes
+
+Director: Michael Bay - Stars: Mark Wahlberg, Nicola Peltz, Ken Watanabe, T.J. Miller, Jack Reynor

+

ab 16.07.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Saal + + Heute + +
+ 30.07.14
+ + Do + +
+ 31.07.14
+ + Fr + +
+ 01.08.14
+ + Sa + +
+ 02.08.14
+ + So + +
+ 03.08.14
+ + Mo + +
+ 04.08.14
+ + Di + +
+ 05.08.14
Saal
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Dawn of the Planet of the Apes (3D/OV) + + +   +

Dawn of the Planet of the Apes (3D/OV)

+

Action | Drama | Sci-Fi - USA 2014
+FSK: 12 - 131 minutes
+
+Preview: August 6 at 8 pm
+Director: Matt Reeves
+Stars: Gary Oldman, Judy Greer, Keri Russell, Andy Serkis, Jimmy Sweetwater

+

ab 06.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + + +
+ Innerhalb der nächsten 7 Tage keine Spielzeit. Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Traumkino: Yves Saint Laurent (Deutsche Fassung) + + +   +

Traumkino: Yves Saint Laurent (Deutsche Fassung)

+

Drama | Biographie - FR 2014
+FSK: 12 - 106 Minuten
+
+Regie: Jalil Lespert - Darsteller: Pierre Niney, Guillaume Gallienne, Charlotte Le Bon, Laura Smet, Marie de Villepin
+
+An jedem 1. und 3. Mittwoch im Monat jeweils um 11 Uhr gibt es für nur 5,- Euro einen ausgewählten Film in der deutschen Sprachfassung.

+

06.08. bis 06.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + + +
+ Innerhalb der nächsten 7 Tage keine Spielzeit. Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Hector and the Search for Happiness (OV) + + +   +

Hector and the Search for Happiness (OV)

+

Adventure | Comedy | Drama - DE/CA 2014
+FSK: 12 - 120 minutes
+
+Preview: August 10 at 8 pm
+Director: Peter Chelsom - Stars: Simon Pegg, Rosamund Pike, Toni Collette, Stellan Skarsgård, Christopher Plummer

+

ab 10.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + + +
+ Innerhalb der nächsten 7 Tage keine Spielzeit. Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: The Expendables 3 (OV) + + +   +

The Expendables 3 (OV)

+

Action | Adventure | Thriller - USA 2014
+FSK: ? - 103 minutes
+
+Preview: August 20 at 8.15 pm
+Director: Patrick Hughes
+Stars: Sylvester Stallone, Jason Statham, Mel Gibson, Harrison Ford, Arnold Schwarzenegger

+

ab 20.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + + +
+ Innerhalb der nächsten 7 Tage keine Spielzeit. Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Doctor Who: Deep Breath + + +   +

Doctor Who: Deep Breath

+

Doctor Who makes a spectacular return to the big screen in the feature-length premiere episode of Series 8; Deep Breath.
+
+August 23 at 8.30 pm

+

23.08. bis 23.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Doctor Who

+ + +
+ + + + + +
+ Innerhalb der nächsten 7 Tage keine Spielzeit. Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + Foto: Traumkino: Boyhood (Deutsche Sprachfassung) + + +   +

Traumkino: Boyhood (Deutsche Sprachfassung)

+

Drama - USA 2014
+FSK: 6 - 166 Minuten
+
+Regie: Richard Linklater - Darsteller: Ellar Coltrane, Patricia Arquette, Ethan Hawke, Lorelei Linklater, Libby Villari
+
+An jedem 1. und 3. Mittwoch im Monat jeweils um 11 Uhr gibt es für nur 5,- Euro einen ausgewählten Film in der deutschen Sprachfassung.

+

20.08. bis 20.08.2014

+ +
+ + Video anschauen + + + + + + + +
+
+ Detailansicht
+

Offizielle Webseite zum Film!

+ + +
+ + + + + +
+ Innerhalb der nächsten 7 Tage keine Spielzeit. Weitere Spielzeiten finden Sie in der Detailansicht. + + + + + + + + +
+ + + + + +
+ + +
+ + + + + +
+ +
+
+ +
+ + + + + + \ No newline at end of file -- 2.7.4