Beispiel #1
0
        public void TestGeneralTimeCurrentWeatherEmptyForecast()
        {
            DateTimeRange range = SamiDateTime.GetDateTimeRange(DateTime.Now);
            Dictionary <String, String> input = new Dictionary <string, string>
            {
                { "Command", "weather" },
                { "Location", "here" },
                { "Time", String.Format("DayOfWeek=today;TimeOfDay={0};", range.ToString().ToLower()) },
            };
            IConfigurationManager configMan = GetConfigurationManager();

            Mock <IWeatherSensor> weatherSensor = new Mock <IWeatherSensor>(MockBehavior.Strict);

            weatherSensor.Setup(s => s.Name).Returns("Mock Weather Sensor");
            weatherSensor.Setup(s => s.IsValid).Returns(true);
            DateTime         today       = DateTime.Now;
            SamiDateTime     samiTime    = new SamiDateTime(today, range);
            WeatherCondition minForecast = new WeatherCondition(DateTime.Now, 70, "Rainy");

            weatherSensor.Setup(s => s.LoadConditions(new Location("Austin", "Texas", 78759))).Returns(minForecast);
            weatherSensor.Setup(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759))).Returns(new List <WeatherCondition>());
            AddComponentToConfigurationManager(weatherSensor.Object);

            Assert.AreEqual("That forecast is not available currently.", RunSingleConversation <WeatherConversation>(input));

            weatherSensor.Verify(s => s.LoadConditions(new Location("Austin", "Texas", 78759)), Times.Exactly(1));
            weatherSensor.Verify(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759)), Times.Exactly(1));
        }
Beispiel #2
0
        public void TestGeneralTimeWeatherNoSecondForecast()
        {
            Dictionary <String, String> input = new Dictionary <string, string>
            {
                { "Command", "weather" },
                { "Location", "here" },
                { "Time", "DayOfWeek=tomorrow;TimeOfDay=evening;" },
            };
            IConfigurationManager configMan = GetConfigurationManager();

            Mock <IWeatherSensor> weatherSensor = new Mock <IWeatherSensor>(MockBehavior.Strict);

            weatherSensor.Setup(s => s.Name).Returns("Mock Weather Sensor");
            weatherSensor.Setup(s => s.IsValid).Returns(true);
            DateTime         tomorrow    = DateTime.Now.AddDays(1);
            SamiDateTime     samiTime    = new SamiDateTime(tomorrow, DateTimeRange.Evening);
            WeatherCondition maxForecast = new WeatherCondition(samiTime.GetMaxTime(), 90, "Sunny");

            weatherSensor.Setup(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759))).Returns(new List <WeatherCondition> {
                maxForecast
            });
            AddComponentToConfigurationManager(weatherSensor.Object);

            Assert.AreEqual("That forecast is not currently available.", RunSingleConversation <WeatherConversation>(input));

            weatherSensor.Verify(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759)), Times.Exactly(1));
        }
Beispiel #3
0
        public void TestGeneralTimeCurrentWeatherStayAtSuccess()
        {
            DateTimeRange range = SamiDateTime.GetDateTimeRange(DateTime.Now);
            Dictionary <String, String> input = new Dictionary <string, string>
            {
                { "Command", "weather" },
                { "Location", "here" },
                { "Time", String.Format("DayOfWeek=today;TimeOfDay={0};", range.ToString().ToLower()) },
            };
            IConfigurationManager configMan = GetConfigurationManager();

            Mock <IWeatherSensor> weatherSensor = new Mock <IWeatherSensor>(MockBehavior.Strict);

            weatherSensor.Setup(s => s.Name).Returns("Mock Weather Sensor");
            weatherSensor.Setup(s => s.IsValid).Returns(true);
            DateTime         today       = DateTime.Now;
            SamiDateTime     samiTime    = new SamiDateTime(today, range);
            WeatherCondition minForecast = new WeatherCondition(DateTime.Now, 70, "Rainy");
            WeatherCondition maxForecast = new WeatherCondition(samiTime.GetMaxTime(), 70, "Sunny");

            weatherSensor.Setup(s => s.LoadConditions(new Location("Austin", "Texas", 78759))).Returns(minForecast);
            weatherSensor.Setup(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759))).Returns(new List <WeatherCondition> {
                maxForecast
            });
            AddComponentToConfigurationManager(weatherSensor.Object);

            String expectedResult = String.Format("According to Mock Weather Sensor. Currently, it is 70 degrees and Rainy. It will stay at 70 degrees by {0} and Sunny..", samiTime.GetMaxTime().ToString("hh:mm tt", CultureInfo.InvariantCulture));

            Assert.AreEqual(expectedResult, RunSingleConversation <WeatherConversation>(input));

            weatherSensor.Verify(s => s.LoadConditions(new Location("Austin", "Texas", 78759)), Times.Exactly(1));
            weatherSensor.Verify(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759)), Times.Exactly(1));
        }
Beispiel #4
0
        public override string Speak()
        {
            Dialog       phrase   = CurrentDialog;
            SamiDateTime time     = ParseTime(phrase.GetPropertyValue("Time"));
            Location     location = ParseLocation(phrase.GetPropertyValue("Location"));

            base.Speak();
            ConversationIsOver = true;

            String result = String.Empty;

            foreach (IWeatherSensor sensor in ConfigManager.FindAllComponentsOfType <IWeatherSensor>())
            {
                String sensorResult = String.Empty;
                if (TryStateForecastForSensor(time, location, sensor, out sensorResult))
                {
                    result += String.Format("According to {0}. {1}.", sensor.Name, sensorResult);
                }
                else if (String.IsNullOrEmpty(result))
                {
                    result = sensorResult;
                }
            }
            return(result);
        }
Beispiel #5
0
        public void TestGeneralTimeWeatherCoolDownSuccess()
        {
            Dictionary <String, String> input = new Dictionary <string, string>
            {
                { "Command", "weather" },
                { "Location", "here" },
                { "Time", "DayOfWeek=tomorrow;TimeOfDay=evening;" },
            };
            IConfigurationManager configMan = GetConfigurationManager();

            Mock <IWeatherSensor> weatherSensor = new Mock <IWeatherSensor>(MockBehavior.Strict);

            weatherSensor.Setup(s => s.Name).Returns("Mock Weather Sensor");
            weatherSensor.Setup(s => s.IsValid).Returns(true);
            DateTime         tomorrow    = DateTime.Now.AddDays(1);
            SamiDateTime     samiTime    = new SamiDateTime(tomorrow, DateTimeRange.Evening);
            WeatherCondition minForecast = new WeatherCondition(samiTime.GetMinTime(), 70, "Rainy");
            WeatherCondition maxForecast = new WeatherCondition(samiTime.GetMaxTime(), 50, "Sunny");

            weatherSensor.Setup(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759))).Returns(new List <WeatherCondition> {
                minForecast, maxForecast
            });
            AddComponentToConfigurationManager(weatherSensor.Object);

            String expectedResult = String.Format("According to Mock Weather Sensor. At {0} tomorrow, it will be 70 degrees and Rainy. It will cool down to 50 degrees by {1} and Sunny..", samiTime.GetMinTime().ToString("hh:mm tt", CultureInfo.InvariantCulture), samiTime.GetMaxTime().ToString("hh:mm tt", CultureInfo.InvariantCulture));

            Assert.AreEqual(expectedResult, RunSingleConversation <WeatherConversation>(input));

            weatherSensor.Verify(s => s.LoadHourlyForecasts(new Location("Austin", "Texas", 78759)), Times.Exactly(1));
        }
Beispiel #6
0
        public void AddAlarm(String message, SamiDateTime time)
        {
            TimeSpan       timeSpan = time.Time - DateTime.Now;
            Timer          timer    = new Timer(timeSpan.TotalMilliseconds);
            ScheduledAlarm newAlarm = new ScheduledAlarm(message, timer, time.Time);

            timer.Elapsed  += (sender, e) => AlarmCallback(newAlarm);
            timer.Enabled   = true;
            timer.AutoReset = false;
            _scheduledAlarms.Add(newAlarm);
        }
Beispiel #7
0
 /// <inheritdoc />
 public IEnumerable <Showtime> GetMovieShowtimes(SamiDateTime timeFilter, String titleFilter = null, String theaterFilter = null)
 {
     UpdateMovieList(timeFilter);
     foreach (Showtime showtime in this._showtimeList)
     {
         if (ShowtimePassesFilter(showtime, titleFilter, theaterFilter, timeFilter))
         {
             yield return(showtime);
         }
     }
 }
Beispiel #8
0
        public override string Speak()
        {
            Dialog        phrase    = CurrentDialog;
            SamiDateTime  time      = ParseTime(phrase.GetPropertyValue("Time"));
            String        teamName  = phrase.GetPropertyValue("Team");
            GameParameter parameter = (GameParameter)Enum.Parse(typeof(GameParameter), phrase.GetPropertyValue("Parameter"));

            ConversationIsOver = true;

            base.Speak();

            IBaseballSensor sensor = ConfigManager.FindAllComponentsOfType <IBaseballSensor>().FirstOrDefault(s => s.Teams.Any(t => t.Key.Equals(teamName)));

            if (sensor != null)
            {
                BaseballTeam team = sensor.Teams.Single(t => t.Key.Equals(teamName));

                switch (parameter)
                {
                case GameParameter.Score:
                    return(RespondForAllGames(sensor, time.Time, team));

                case GameParameter.Standings:
                    return(RespondToStandings(sensor, team));

                case GameParameter.MLBTVFreeGame:
                    return(RespondToMLBTVGame(sensor));

                case GameParameter.TVChannel:
                    return(RespondToTVChannel(sensor, team, time.Time));

                case GameParameter.TurnToGame:
                    return(RespondToTurnToGame(sensor, team, time.Time));

                default:
                    return(String.Empty);
                }
            }
            else if (parameter == GameParameter.MLBTVFreeGame)
            {
                sensor = ConfigManager.FindAllComponentsOfType <IBaseballSensor>().FirstOrDefault(s => s.League.Equals("MLB"));
                if (sensor != null)
                {
                    return(RespondToMLBTVGame(sensor));
                }
            }
            return(String.Empty);
        }
Beispiel #9
0
        public void TestGeneralTimeCurrentWeatherFailInPast()
        {
            DateTimeRange range = SamiDateTime.GetDateTimeRange(DateTime.Now);
            Dictionary <String, String> input = new Dictionary <string, string>
            {
                { "Command", "weather" },
                { "Location", "here" },
                { "Time", String.Format("DayOfWeek=yesterday;TimeOfDay={0};", range.ToString().ToLower()) },
            };
            IConfigurationManager configMan = GetConfigurationManager();

            Mock <IWeatherSensor> weatherSensor = new Mock <IWeatherSensor>(MockBehavior.Strict);

            weatherSensor.Setup(s => s.Name).Returns("Mock Weather Sensor");
            weatherSensor.Setup(s => s.IsValid).Returns(true);
            AddComponentToConfigurationManager(weatherSensor.Object);

            Assert.AreEqual("I'm sorry, I can not get a forcast for the past.", RunSingleConversation <WeatherConversation>(input));
        }
Beispiel #10
0
        public override string Speak()
        {
            base.Speak();
            ConversationIsOver = true;

            Dialog phrase = CurrentDialog;

            String alarmType = phrase.GetPropertyValue("SubCommand");

            if (alarmType.Equals("Time"))
            {
                // A specific time has been requested
                SamiDateTime alarmTime     = ParseTime(phrase.GetPropertyValue("Time"));
                String       alarmResponse = "Your " + alarmTime.Time.ToShortTimeString() + " alarm is complete.";
                _manager.AddAlarm(alarmResponse, alarmTime);
                return("The alarm has been set to " + alarmTime.Time.ToShortTimeString());
            }
            else if (alarmType.Equals("Duration"))
            {
                // A duration has been requested.
                int      seconds = Convert.ToInt32(phrase.GetPropertyValue("Seconds"));
                int      minutes = Convert.ToInt32(phrase.GetPropertyValue("Minutes"));
                int      hours   = Convert.ToInt32(phrase.GetPropertyValue("Hours"));
                TimeSpan ts      = new TimeSpan(hours, minutes, seconds);
                if (ts.TotalSeconds == 0)
                {
                    return("");
                }
                else
                {
                    String alarmResponse = "Your " + SayTime(ts, false) + " timer is complete";
                    _manager.AddAlarm(alarmResponse, ts);
                    return("The timer has been set to " + SayTime(ts, true) + ".");
                }
            }
            else if (alarmType.Equals("List"))
            {
                List <ScheduledAlarm> alarms = _manager.GetScheduledAlarms();
                String response = "You have " + alarms.Count;
                if (alarms.Count == 1)
                {
                    response += " alarm scheduled. ";
                }
                else
                {
                    response += " alarms scheduled. ";
                }

                if (alarms.Count > 0)
                {
                    List <String> alarmStatus = new List <String>();
                    foreach (ScheduledAlarm alarm in alarms)
                    {
                        if (alarm.IsDurationAlarm)
                        {
                            alarmStatus.Add(SayTime(alarm.TimeLeft, true) + " left on your " + SayTime(alarm.TotalDuration, false) + " alarm");
                        }
                        else
                        {
                            alarmStatus.Add(SayTime(alarm.TimeLeft, true) + " left on your " + alarm.AlarmTime.ToShortTimeString() + " alarm");
                        }
                    }
                    response += "You have " + SayList(alarmStatus);
                }
                return(response);
            }
            else if (alarmType.Equals("DeleteLast"))
            {
                ScheduledAlarm deletedAlarm = _manager.DeleteLastAlarm();
                if (deletedAlarm == null)
                {
                    return("There are no alarms to delete.");
                }
                else
                {
                    if (deletedAlarm.IsDurationAlarm)
                    {
                        return("Deleted the " + SayTime(deletedAlarm.TotalDuration, false) + " alarm");
                    }
                    else
                    {
                        return("Deleted the " + deletedAlarm.AlarmTime.ToShortTimeString() + " alarm");
                    }
                }
            }
            else if (alarmType.Equals("DeleteAll"))
            {
                if (_manager.DeleteAllAlarms())
                {
                    return("Deleted all alarms.");
                }
                else
                {
                    return("There are no alarms to delete.");
                }
            }
            else
            {
                return("The alarm type " + alarmType + " is not valid.");
            }
        }
Beispiel #11
0
        private static bool TryStateForecastForSensor(SamiDateTime time, Location location, IWeatherSensor sensor, out String message)
        {
            if (time.Range == DateTimeRange.Now)
            {
                WeatherCondition condition = sensor.LoadConditions(location);
                if (condition == null)
                {
                    message = "Weather conditions are not available right now.";
                    return(false);
                }
                message = String.Format("Right now, it is {0} degrees and {1}.",
                                        condition.Temperature,
                                        condition.ConditionDescription);
                return(true);
            }
            else if (time.Range == DateTimeRange.Day)
            {
                // We are asking about a specific day, not a specific time.
                IEnumerable <DailyForecast> forecasts = sensor.LoadDailyForecasts(location);
                if (forecasts == null)
                {
                    message = "That forecast is not currently available.";
                    return(false);
                }
                DailyForecast forecast = forecasts.SingleOrDefault(f => f.High.Time.Date.Equals(time.Time.Date));
                if (forecast == null)
                {
                    message = "That forecast is not currently available.";
                    return(false);
                }
                message = String.Format("On {0}, it will be between {2} and {1} degrees and {3}.",
                                        time.Time.ToString("m", CultureInfo.InvariantCulture),
                                        forecast.High.Temperature,
                                        forecast.Low.Temperature,
                                        forecast.Low.ConditionDescription);
                return(true);
            }
            else if (time.Range == DateTimeRange.SpecificTime)
            {
                // Make sure we're not trying to get the time in the past
                if (time.Time < DateTime.Now)
                {
                    message = "I'm sorry, I can not get a forcast for the past.";
                    return(false);
                }

                // We want a specific time.
                WeatherCondition condition = sensor.LoadHourlyForecasts(location).SingleOrDefault(c => c.Time.Equals(new DateTime(time.Time.Year, time.Time.Month, time.Time.Day, time.Time.Hour, 0, 0)));
                if (condition == null)
                {
                    message = "That forecast is not available currently.";
                    return(false);
                }
                if (time.Time.Day == DateTime.Today.Day)
                {
                    message = String.Format("Today at {0}, it will be {1} degrees and {2}.",
                                            time.Time.ToString("hh:mm tt", CultureInfo.InvariantCulture),
                                            condition.Temperature,
                                            condition.ConditionDescription);
                    return(true);
                }
                else
                {
                    message = String.Format("On {0} at {1}, it will be {2} degrees and {3}.",
                                            time.Time.ToString("m", CultureInfo.InvariantCulture),
                                            time.Time.ToString("hh:mm tt", CultureInfo.InvariantCulture),
                                            condition.Temperature,
                                            condition.ConditionDescription);
                    return(true);
                }
            }
            else if (time.Range == DateTimeRange.EarlyMorning ||
                     time.Range == DateTimeRange.Morning ||
                     time.Range == DateTimeRange.Afternoon ||
                     time.Range == DateTimeRange.Evening ||
                     time.Range == DateTimeRange.Night)
            {
                DateTime firstTime  = time.GetMinTime();
                DateTime secondTime = time.GetMaxTime();

                // Make sure we're not trying to get the time in the past
                if (secondTime < DateTime.Now)
                {
                    message = "I'm sorry, I can not get a forcast for the past.";
                    return(false);
                }

                double firstTemp, secondTemp;

                if (firstTime < DateTime.Now)
                {
                    // We are already in the time span requested.
                    WeatherCondition condition = sensor.LoadConditions(location);
                    IEnumerable <WeatherCondition> forecasts = sensor.LoadHourlyForecasts(location);
                    WeatherCondition forecast = forecasts == null ? null : forecasts.SingleOrDefault(c => c.Time.Equals(new DateTime(secondTime.Year, secondTime.Month, secondTime.Day, secondTime.Hour, 0, 0)));

                    if (condition == null || forecast == null)
                    {
                        message = "That forecast is not available currently.";
                        return(false);
                    }

                    firstTemp  = condition.Temperature;
                    secondTemp = forecast.Temperature;

                    String temperatureCompare;

                    if (firstTemp < secondTemp)
                    {
                        temperatureCompare = "warm up to";
                    }
                    else if (firstTemp > secondTemp)
                    {
                        temperatureCompare = "cool down to";
                    }
                    else
                    {
                        temperatureCompare = "stay at";
                    }

                    message = String.Format("Currently, it is {0} degrees and {1}. It will {2} {3} degrees by {4} and {5}.",
                                            firstTemp,
                                            condition.ConditionDescription,
                                            temperatureCompare,
                                            secondTemp,
                                            secondTime.ToString("hh:mm tt", CultureInfo.InvariantCulture),
                                            forecast.ConditionDescription);
                    return(true);
                }
                else
                {
                    // We want a specific time.
                    IEnumerable <WeatherCondition> forecasts = sensor.LoadHourlyForecasts(location);
                    WeatherCondition firstForecast           = forecasts == null ? null : forecasts.SingleOrDefault(c => c.Time.Equals(new DateTime(firstTime.Year, firstTime.Month, firstTime.Day, firstTime.Hour, 0, 0)));
                    WeatherCondition secondForecast          = forecasts == null ? null : forecasts.SingleOrDefault(c => c.Time.Equals(new DateTime(secondTime.Year, secondTime.Month, secondTime.Day, secondTime.Hour, 0, 0)));

                    if (firstForecast == null || secondForecast == null)
                    {
                        message = "That forecast is not currently available.";
                        return(false);
                    }

                    // "At (time) (nothing|tomorrow|on day), it will be (firsttemp) degrees and (firstcondition). It will (warm up to|cool down to|stay at) (secondtemp) degrees and be (secondcondition)."
                    // Deturmine how to say the day
                    String day;
                    if (time.Time.Date == DateTime.Today.Date)
                    {
                        // Today
                        day = "today";
                    }
                    else if (time.Time.Date == DateTime.Today.AddDays(1).Date)
                    {
                        // Tomorrow
                        day = "tomorrow";
                    }
                    else
                    {
                        // Some other day
                        day = "on " + time.Time.ToString("m", CultureInfo.InvariantCulture);
                    }
                    firstTemp  = firstForecast.Temperature;
                    secondTemp = secondForecast.Temperature;

                    String temperatureCompare;

                    if (firstTemp < secondTemp)
                    {
                        temperatureCompare = "warm up to";
                    }
                    else if (firstTemp > secondTemp)
                    {
                        temperatureCompare = "cool down to";
                    }
                    else
                    {
                        temperatureCompare = "stay at";
                    }


                    message = String.Format("At {0} {1}, it will be {2} degrees and {3}. It will {4} {5} degrees by {6} and {7}.",
                                            firstTime.ToString("hh:mm tt", CultureInfo.InvariantCulture),
                                            day,
                                            firstTemp,
                                            firstForecast.ConditionDescription,
                                            temperatureCompare,
                                            secondTemp,
                                            secondTime.ToString("hh:mm tt", CultureInfo.InvariantCulture),
                                            secondForecast.ConditionDescription);
                    return(true);
                }
            }
            message = "Not Supported";
            return(false);
        }
Beispiel #12
0
        internal void UpdateMovieList(SamiDateTime date)
        {
            try
            {
                String url = "http://data.tmsapi.com/v1/movies/showings?" +
                             "startDate=" + date.Time.ToString("yyyy-MM-dd") +
                             "&zip=" + _configManager.LocalLocation.ZipCode +
                             "&radius=" + _searchRadius +
                             "&api_key=" + _apiKey;
                String jsonResults = new WebClient().DownloadString(url);
                jsonResults = "{\"movies\":" + jsonResults + "}";

                var movieJson = DynamicJson.Parse(jsonResults);

                foreach (var movie in movieJson.movies)
                {
                    String movieTitle, rating, description;
                    movieTitle = movie.title;
                    // Define rating and description as empty strings in case they are not defined.
                    rating      = "";
                    description = "";
                    if (movie.IsDefined("ratings"))
                    {
                        if (movie.ratings[0].IsDefined("code"))
                        {
                            rating = movie.ratings[0].code;
                        }
                    }
                    if (movie.IsDefined("shortDescription"))
                    {
                        description = movie.shortDescription;
                    }

                    Movie m = new Movie(movieTitle, description, rating);
                    if (!this._movieList.Contains(m))
                    {
                        this._movieList.Add(m);
                    }
                    foreach (dynamic showtime in movie.showtimes)
                    {
                        String   theaterName   = showtime.theatre.name;
                        String   movieTime     = showtime.dateTime;
                        Showtime movieShowtime = new Showtime(movieTitle, theaterName, movieTime);
                        if (!this._showtimeList.Contains(movieShowtime))
                        {
                            this._showtimeList.Add(movieShowtime);
                        }
                    }
                }

                // Clear out old entries
                List <Showtime> newList = new List <Showtime>();
                foreach (Showtime showtime in this._showtimeList)
                {
                    if (showtime.Time >= DateTime.Now)
                    {
                        newList.Add(showtime);
                    }
                }
                this._showtimeList = newList;
            }
            catch (Exception)
            {
            }
        }
Beispiel #13
0
        private static Boolean ShowtimePassesFilter(Showtime showtime, String titleFilter, String theaterFilter, SamiDateTime timeFilter)
        {
            // See if the showtime is in a certain time
            if (!timeFilter.TimeIsInRange(showtime.Time))
            {
                // The time is not in the range
                return(false);
            }

            if (!String.IsNullOrEmpty(titleFilter))
            {
                if (!showtime.MovieTitle.Equals(titleFilter))
                {
                    return(false);
                }
            }

            if (!String.IsNullOrEmpty(theaterFilter))
            {
                if (!showtime.Theater.Equals(theaterFilter))
                {
                    return(false);
                }
            }

            // We've hit this point, so we passed the filter
            return(true);
        }
Beispiel #14
0
        public override string Speak()
        {
            String       returnString = String.Empty;
            Dialog       phrase       = CurrentDialog;
            String       title        = phrase.GetPropertyValue("Title");
            String       theater      = phrase.GetPropertyValue("Theater");
            SamiDateTime samiTime     = ParseTime(phrase.GetPropertyValue("Time"));

            base.Speak();
            ConversationIsOver = true;
            IEnumerable <IMovieSensor> movieDatabases = ConfigManager.FindAllComponentsOfType <IMovieSensor>();

            switch (phrase.GetPropertyValue("SubCommand"))
            {
            case "Names":
                // Return a list of movie titles
                List <String> movieTitles = movieDatabases.SelectMany(s => s.GetMovieShowtimes(samiTime, theaterFilter: theater).Select(showtime => showtime.MovieTitle)).Distinct().ToList();
                if (movieTitles.Count > 0)
                {
                    returnString  = "On " + samiTime.Time.ToString("MMMM d", CultureInfo.InvariantCulture);
                    returnString += ", these movies will be playing. ";

                    returnString += SayList(movieTitles);
                    return(returnString);
                }
                else
                {
                    return("I'm sorry, no movies will be shown then.");
                }

            case "Showtimes":
                // Return a list of showtimes
                IEnumerable <Showtime> showtimes = movieDatabases.SelectMany(s => s.GetMovieShowtimes(samiTime, title, theater)).ToList();

                if (showtimes.Any())
                {
                    String lastTheater = "";
                    returnString = "On " + samiTime.Time.ToString("MMMM d", CultureInfo.InvariantCulture) + ", ";
                    foreach (Showtime showtime in showtimes)
                    {
                        if (!showtime.Theater.Equals(lastTheater))
                        {
                            returnString += showtime.MovieTitle + " will be shown at " + showtime.Theater + " at ";
                        }

                        returnString += showtime.Time.ToString("hh:mm") + " . ";

                        lastTheater = showtime.Theater;
                    }
                    return(returnString);
                }
                else
                {
                    return("I'm sorry, " + title + " will not be shown then.");
                }

            case "Description":
                IEnumerable <String> descriptions = movieDatabases.Select(s => s.GetMovieDescription(title)).Where(d => !String.IsNullOrEmpty(d)).ToList();
                if (descriptions.Any())
                {
                    return(descriptions.FirstOrDefault());
                }
                else
                {
                    return(String.Format("I can't find the description for {0}.", title));
                }

            case "Rating":
                IEnumerable <String> ratings = movieDatabases.Select(s => s.GetMovieRating(title)).Where(d => !String.IsNullOrEmpty(d)).ToList();
                if (ratings.Any())
                {
                    return(String.Format("{0} is rated {1}.", title, ratings.FirstOrDefault()));
                }
                else
                {
                    return(String.Format("I can't find the rating for {0}.", title));
                }

            default:
                return("The movie sub command " + phrase.GetPropertyValue("Subcommand") + " is not recognized.");
            }
        }