Trivia oyunları, yeni gerçekleri öğrenebileceğiniz ve çeşitli konularda bilginizi genişletebileceğiniz ilgi çekici ve eğitici bir deneyim sunar. Günümüzde Trivia quiz mobil ve web uygulamaları bu tür bir aktivite için en sık başvurulan alanlardır. WhatsApp'ta bilgi yarışması oyunu oynamaya ne dersiniz? Bu eğitim kılavuzunda, Twilio for WhatsApp, ASP.NET Core ve ASP.NET Core'u kullanarak bir bilgi yarışması uygulamasının nasıl oluşturulacağını öğreneceksiniz. ( ). Bu eğitimin amacı, kullanıcıların WhatsApp kullanarak çoktan seçmeli soruları oynamasına ve yanıtlamasına olanak tanıyan bir trivia oyun uygulaması oluşturmaktır. Sen yararlanacaksın Kullanıcı ilerlemesini depolamak ve almak, puanı takip etmek ve oyun durumunu korumak için. Trivia API'si CC BY-NC 4.0 kapsamında lisanslanmıştır ASP.NET Core'daki oturumlar Bu soruları almak için geliştiricilerin çoktan seçmeli bilgi soruları sunarak sınav uygulamaları oluşturmasını kolaylaştıran bir REST API olan Trivia API'yi kullanacaksınız. Trivia API'si hakkında daha fazla bilgi edinmek için lütfen__ ziyaret edin. Trivia API belgelerini__ Önkoşullar Bu öğreticiyi tamamlamak için ihtiyacınız olacak: .NET'i destekleyen bir işletim sistemi (Windows/macOS/Linux) .NET 7 SDK'sı Bir kod düzenleyici veya IDE (Önerilen: , ile , veya ) Görsel stüdyo Visual Studio Kodu C# eklentisi JetBrains Sürücüsü ngrok CLI Ücretsiz veya ücretli bir Twilio Hesabı (Eğer hesabınız yoksa, ) Twilio'yu ücretsiz deneyin C# ve ASP.NET Core deneyimi . Bu eğitimin kaynak kodunu GitHub'da bulabilirsiniz Yeni bir ASP.NET Core projesi ayarlama Başlamak için tercih edilen bir çalışma dizininde kabuk terminalinizi kullanarak yeni bir web API projesi oluşturmak üzere aşağıdaki komutları çalıştırın: dotnet new webapi -n TwilioWhatsAppTriviaApp --no-openapi Yukarıdaki kod parçasındaki ikinci komut, belirtilen adla ve OpenAPI (Swagger) desteği olmadan yeni bir web API projesi oluşturacaktır. Projede Swagger'ı kullanmak istiyorsanız yukarıdaki komutta komutunu atlamanız yeterlidir. --no-openapi Bu komutu çalıştırarak proje dizinine geçin: cd TwilioWhatsAppTriviaApp Yükle NuGet paketi: ASP.NET Core için Twilio Yardımcı kitaplığı dotnet add package Twilio.AspNet.Core Bu kitaplık, bir ASP.NET Core uygulamasında Twilio web kancaları ve API'lerle çalışmayı kolaylaştırır. Tercih ettiğiniz IDE'yi kullanarak projeyi açın. klasöründe, ortak şablon denetleyici dosyası kaldırın ve ayrıca proje dizinindeki dosyasını da kaldırın. Denetleyiciler WeatherForecastController.cs'yi WeatherForcast.cs Şu ana kadar yaptığınız her şeyin iyi çalıştığından emin olmak için aşağıdaki komutları kullanarak projenizi oluşturun ve çalıştırın: dotnet build dotnet run Projeyi başarıyla çalıştırdıktan sonra hata ayıklama konsolunda görünen localhost URL'lerinden herhangi birini not edin. Ngrok'u kullanarak herkesin erişebileceği bir yerel web sunucusu kurmak için bu URL'lerden herhangi birini kullanabilirsiniz. Oturumları Uygulama Oturumlar, bir kullanıcının verilerini ASP.NET Core uygulamasında depolamanın çeşitli yollarından biridir. Varsayılan olarak HTTP protokolü durum bilgisiz olduğundan, yani veriler korunmadığından, kullanıcı verilerini istekler arasında tutmak istediğinizde bu çok önemlidir. Aşağıdaki kodda gösterildiği gibi dosyasını değiştirerek bellek içi oturum sağlayıcısını ekleyin: Program.cs var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(40); options.Cookie.IsEssential = true; }); var app = builder.Build(); app.UseSession(); app.MapControllers(); app.Run(); dağıtılmış bellek önbellek hizmetini kaydeder. Bu hizmet, birden fazla istek veya oturumda veri depolamak ve almak için kullanılabilecek bir bellek içi önbellek sağlar. AddDistributedMemoryCache() , oturum hizmetlerini kaydederek uygulamanın oturum durumunu korumasını sağlar. parametresi oturumla ilgili çeşitli seçenekleri yapılandırmanıza olanak tanır. oturumun boşta sayılacağı eylemsizlik süresini ayarlamak için kullanılır. Bu durumda 40 saniyeye ayarlanır. , çerez reddinin etkinleştirildiği senaryolarda bile oturumun durumunun işlevsel kalmasını sağlar. AddSession() options IdleTimeout Cookie.IsEssential Oturum desteği, ara yazılımının uygulama hattına eklenmesiyle etkinleştirilir; yani uygulamanız, verileri depolamak ve almak için kullanılabilecek bir oturum nesnesine erişim kazanır. UseSession Modelleri Oluşturun Proje dizininizde adında yeni bir klasör oluşturun. Aşağıdaki kod örneklerinde gösterildiği gibi özelliklere sahip iki model sınıf dosyası ( ve ekleyin: Modeller TriviaApiResponse.cs Question.cs) using Newtonsoft.Json; namespace TwilioWhatsAppTriviaApp.Models; public class TriviaApiResponse { [JsonProperty("category")] public string Category { get; set; } [JsonProperty("correctAnswer")] public string CorrectAnswer { get; set; } [JsonProperty("incorrectAnswers")] public List<string> IncorrectAnswers { get; set; } [JsonProperty("question")] public string Question { get; set; } [JsonProperty("type")] public string? Type { get; set; } [JsonProperty("difficulty")] public string Difficulty { get; set; } } namespace TwilioWhatsAppTriviaApp.Models; public class Question { public string QuestionText { get; set; } public List<(string option, bool isCorrect)> Options { get; set; } } modeli, Trivia API yanıtının alanlarını temsil eden özellikleri içerir. özelliği, her özelliğin karşılık gelen JSON verileriyle doğru şekilde doldurulmasını sağlar. TriviaApiResponse JsonProperty Trivia sorularını basitleştirilmiş bir şekilde ele almak için sınıfı kurtarmaya geliyor. Bu sınıf, soru metni ve seçenekler listesi de dahil olmak üzere, önemsiz bir soru için gerekli bilgileri içerir. Her seçenek, seçenek metnini içeren bir tanımlama grubu ve bunun doğru seçenek olup olmadığını gösteren bir boole değeriyle temsil edilir. Question Trivia Hizmet Sınıfını Ekle Proje dizininizde bir klasörü oluşturun ve adlı yeni bir sınıf dosyası ekleyin. Aşağıdaki kodda gösterildiği gibi içeriğini değiştirin: Hizmetler TriviaService.cs using Newtonsoft.Json; using TwilioWhatsAppTriviaApp.Models; namespace TwilioWhatsAppTriviaApp.Services; public class TriviaService { private const string TheTriviaApiUrl = @"https://the-trivia-api.com/api/questions?limit=3"; private HttpClient httpClient; public TriviaService(HttpClient httpClient) { this.httpClient = httpClient; } public async Task<IEnumerable<TriviaApiResponse>> GetTrivia() { var response = await httpClient.GetAsync(TheTriviaApiUrl); var triviaJson = await response.Content.ReadAsStringAsync(); var trivia = JsonConvert.DeserializeObject<IEnumerable<TriviaApiResponse>>(triviaJson); return trivia; } public List<Question> ConvertTriviaToQuestions(IEnumerable<TriviaApiResponse> questions) { List<Question> newQuestions = new(); foreach (var question in questions) { var options = new List<(string option, bool isCorrect)>() { (question.CorrectAnswer, true), (question.IncorrectAnswers[0], false), (question.IncorrectAnswers[1], false), (question.IncorrectAnswers[2], false) }; // Shuffle the options randomly Random random = new(); options = options.OrderBy(_ => random.Next()).ToList(); newQuestions.Add(new Question { QuestionText = question.Question, Options = options }); } return newQuestions; } } sınıfı iki yöntem içerir: ve . yöntemi, HTTP GET isteğini Trivia API'sine, yalnızca 3 sorunun döndürülmesi gerektiğini belirten sorgu parametresiyle gönderir. Limit parametresi olmadan API varsayılan olarak 10 soru döndürür. TriviaService GetTrivia ConvertTriviaToQuestions GetTrivia limit=3 yöntemi, API'den gelen yanıtı organize bir şekilde dönüştürür. Yöntem ayrıca tüm soru seçeneklerini rastgele karıştırır, böylece tek bir seçenek tüm soruların yanıtı olmaz. ConvertTriviaToQuestions ve HTTP istemcisini uygulamanızın Dependency Injection (DI) kapsayıcısına kaydetmek için aşağıdaki kodda gösterildiği gibi değiştirin: TriviaService Program.cs'yi using TwilioWhatsAppTriviaApp.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(40); options.Cookie.IsEssential = true; }); builder.Services.AddHttpClient(); builder.Services.AddScoped<TriviaService>(); var app = builder.Build(); app.UseSession(); app.MapControllers(); app.Run(); Trivia Denetleyicisini Oluşturun adlı bir dosyaya boş bir API denetleyici sınıfını klasörüne ekleyin ve içeriğini aşağıdaki kodda gösterildiği gibi değiştirin: TriviaController.cs Denetleyiciler using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Twilio.AspNet.Core; using Twilio.TwiML; using Twilio.TwiML.Messaging; using TwilioWhatsAppTriviaApp.Models; using TwilioWhatsAppTriviaApp.Services; namespace WhatsappTrivia.Controllers; [Route("[controller]")] [ApiController] public class TriviaController : TwilioController { private const string SessionKeyIsGameOn = "IsGameOn"; private const string SessionKeyScore = "Score"; private const string SessionKeyCurrentQuestionIndex = "CurrentQuestionIndex"; private const string SessionKeyTotalQuestions = "TotalQuestions"; private const string SessionKeyQuestions = "Questions"; private static readonly string[] StartCommands = { "START", "S" }; private static readonly string[] OptionValues = { "A", "B", "C", "D" }; private readonly TriviaService triviaService; public TriviaController(TriviaService triviaService) { this.triviaService = triviaService; } [HttpPost] public async Task<IActionResult> Index() { var response = new MessagingResponse(); var form = await Request.ReadFormAsync(); var body = form["Body"].ToString().ToUpper().Trim(); await HttpContext.Session.LoadAsync(); var isGameOn = Convert.ToBoolean(HttpContext.Session.GetString(SessionKeyIsGameOn)); int currentQuestionIndex = HttpContext.Session.GetInt32(SessionKeyCurrentQuestionIndex) ?? 0; int totalQuestions = HttpContext.Session.GetInt32(SessionKeyTotalQuestions) ?? 0; if (StartCommands.Contains(body) && !isGameOn) { await StartGame(); HttpContext.Session.SetString(SessionKeyIsGameOn, "true"); response.Message(PresentQuestionWithOptions(currentQuestionIndex)); return TwiML(response); } if (OptionValues.Contains(body) && isGameOn) { var result = ProcessUserAnswer(body, currentQuestionIndex); response.Message(result); currentQuestionIndex++; if (currentQuestionIndex <= totalQuestions - 1) { HttpContext.Session.SetInt32(SessionKeyCurrentQuestionIndex, currentQuestionIndex); response.Append(new Message(PresentQuestionWithOptions(currentQuestionIndex))); } else { response.Append(new Message(EndTrivia())); } return TwiML(response); } response.Message(!isGameOn ? "*Hello! Send 'Start' or 'S' to play game*" : "*Invalid Input! Send a correct option 'A', 'B', 'C' or 'D'*"); return TwiML(response); } private async Task StartGame() { if (HttpContext.Session.GetString(SessionKeyQuestions) != null) { HttpContext.Session.Remove(SessionKeyQuestions); } var trivia = await this.triviaService.GetTrivia(); var questions = this.triviaService.ConvertTriviaToQuestions(trivia); AddNewQuestionsToSession(questions); HttpContext.Session.SetInt32(SessionKeyTotalQuestions, questions.Count); } private string ProcessUserAnswer(string userAnswer, int questionIndex) { bool optionIsCorrect = false; int score = HttpContext.Session.GetInt32(SessionKeyScore) ?? 0; var question = RetrieveQuestionFromSession(questionIndex); switch (userAnswer) { case "A": optionIsCorrect = question.Options[0].isCorrect; break; case "B": optionIsCorrect = question.Options[1].isCorrect; break; case "C": optionIsCorrect = question.Options[2].isCorrect; break; case "D": optionIsCorrect = question.Options[3].isCorrect; break; } if (optionIsCorrect) { score++; HttpContext.Session.SetInt32(SessionKeyScore, score); } return optionIsCorrect ? "_Correct ✅_" : $"_Incorrect ❌ Correct answer is {question.Options.Find(o => o.isCorrect).option.TrimEnd()}_"; } private string PresentQuestionWithOptions(int questionIndex) { var question = RetrieveQuestionFromSession(questionIndex); return $""" {questionIndex + 1}. {question.QuestionText} {OptionValues[0]}. {question.Options[0].option} {OptionValues[1]}. {question.Options[1].option} {OptionValues[2]}. {question.Options[2].option} {OptionValues[3]}. {question.Options[3].option} """; } private void AddNewQuestionsToSession(List<Question> questions) => HttpContext.Session.SetString(SessionKeyQuestions, JsonConvert.SerializeObject(questions)); private Question RetrieveQuestionFromSession(int questionIndex) { var questionsFromSession = HttpContext.Session.GetString(SessionKeyQuestions); return JsonConvert.DeserializeObject<List<Question>>(questionsFromSession)[questionIndex]; } private string EndTrivia() { var score = HttpContext.Session.GetInt32(SessionKeyScore) ?? 0; var totalQuestions = HttpContext.Session.GetInt32(SessionKeyTotalQuestions) ?? 0; var userResult = $""" Thanks for playing! 😊 You answered {score} out of {totalQuestions} questions correctly. To play again, send 'Start' or 'S' """; HttpContext.Session.Clear(); return userResult; } } Bu denetleyici sınıfı, gelen iletilerin işlenmesinden, oturum durumunun yönetilmesinden ve yanıtların oluşturulmasından sorumludur. Twilio.AspNet.Core kitaplığı tarafından sağlanan ve yöntemine erişmenizi sağlayan sınıfından miras alır. Yanıt vermek için bu yöntemi kullanabilirsiniz. . sınıfı, oturumla etkileşim kurmak için yöntemlerini kullanır. Geçerli girişler, ve salt okunur dizilerindeki öğelerdir. Kullanıcının doğru bir giriş gönderdiğinden emin olmak için gelen mesajın gövdesi bu öğelerle karşılaştırılır, aksi takdirde kullanıcıya oyunun mevcut durumuna göre doğru girişi yapmasını isteyen bir mesaj gönderilir. “SessionKey” ön ekine sahip diğer alanlar, programdaki oturum anahtarlarına özel sabit dizileri tanımlamak için kullanılır. TwiML TwilioController Twilio İşaretleme Dili olan TwiML TriviaController HttpContext.Session StartCommands OptionValues yöntemi, WhatsApp'tan yolu aracılığıyla gelen HTTP POST isteklerini işleyen ana eylem yöntemidir. Oturum verilerini kullanarak yükler ve ve yöntemlerini kullanarak oyun durumuna ilişkin verileri oturumdan alır. Index /Trivia HttpContext.Session.LoadAsync() HttpContext.Session.GetString() HttpContext.Session.GetInt32() Belirli dizelerin başında ve sonunda alt çizgi (_) ve yıldız işaretlerinin (*) kullanılması, oluşturulan WhatsApp mesajlarında sırasıyla italik ve kalın metin formatı elde etmek içindir. her yardımcı yöntem, sınıfın ana işlevselliğini destekleyen belirli bir görevi gerçekleştirir. TriviaController yöntemi trivia sorularını alarak, bunları oyuna uygun formata dönüştürerek ve oturumda saklayarak oyunu başlatır. StartGame yöntemi kullanıcının bir soruya verdiği yanıtı işleyerek yanıtın doğru olup olmadığını belirler. ProcessUserAnswer yöntemi, bir soruyu seçenekleriyle birlikte biçimlendirmekten ve sunmaktan sorumludur. PresentQuestionWithOptions yöntemi oturumdaki soruların bir listesini saklar. Soruları JSON formatına dönüştürür ve JSON dizesini oturuma kaydeder. AddNewQuestionsToSession yöntemi, soru dizinini kullanarak oturumdan bir soruyu alır. RetrieveQuestionFromSession yöntemi trivia oyununu sonlandırmak için bir mesaj üretir. Bu yöntem aynı zamanda oyuna ilişkin oturum verilerini de kaldırır. oturum hizmetinin yapılandırmasına bağlı olarak, oturum 40 saniye boyunca boşta kaldığında bu işlem otomatik olarak gerçekleşir. EndTrivia Program.cs'deki Uygulamayı Test Edin Uygulamayı test etmek için WhatsApp için Twilio Sandbox'ı kurmanız, uygulama uç noktanızı herkese açık hale getirmeniz ve uç nokta URL'sini Sandbox yapılandırmasına bir web kancası olarak eklemeniz gerekir. WhatsApp için Twilio Sandbox'ı kurun Şuraya git: gidin. Twilio Konsolu Mesaj > Deneyin > WhatsApp Mesajı Gönder seçeneğine WhatsApp sanal alanıyla başarılı bir bağlantı oluşturmak için cihazınızdan verilen Twilio numarasına bir WhatsApp mesajı göndererek sanal alana bağlanmak için sayfadaki talimatları izleyin. Benzer şekilde uygulamanızı kendi numaralarıyla test etmek isteyen diğer kişilerin de aynı prosedürü izlemesi gerekecektir. Test için ngrok kullanarak web kancanızı gösterin Şimdi, bir kabuk terminali açın ve ngrok'u başlatmak ve yerel ASP.NET Core uygulamanızı ortaya çıkarmak için yerine başlangıçta kopyaladığınız localhost'un tam URL'sini koymak için aşağıdaki komutu çalıştırın: <localhost-url> ngrok http <localhost-url> ngrok, istekleri yerel ASP.NET uygulamanıza ileten genel bir URL oluşturacaktır. Ngrok terminal penceresinde etiketli yönlendirme URL'sini arayın ve kopyalayın. Yönlendirme Twilio WhatsApp'ı Deneyin sayfasına geri dönün, tıklayın ve Uç noktadaki URL'yi ngrok artı rotası tarafından oluşturulan URL'si ile değiştirin ve yöntemin POST olarak ayarlandığından emin olun. Daha sonra yeni korumalı alan yapılandırmasını kaydetmek için Kaydet'i tıklayın. Sandbox Ayarları'na mesaj geldiğinde /Trivia yönlendirme Proje Demosu ASP.NET Core projenizi aşağıdaki komutu kullanarak çalıştırın: dotnet run Şimdi, ilk görüşmede Twilio Sandbox numarasıyla bir mesaj göndererek uygulamanızı test edin. Çözüm Twilio platformunun ve WhatsApp'ın gücünden yararlanarak, kullanıcıların keyif alabileceği sürükleyici bir bilgi oyunu deneyimi yarattınız. Ayrıca oturumlardaki verileri nasıl kaydedeceğinizi ve alacağınızı da öğrendiniz. Bu projenin geliştirilebilmesinin birkaç yolu vardır. Zamanlayıcı ekleyerek, istisnaları ele alarak, kullanıcıların zorluk seçmesine izin vererek ve seçilen zorluğu Trivia API URL'si (örn. ). Ayrıca kullanıcıların WhatsApp aracılığıyla anket doldurmasına olanak tanıyan bir çözüm oluşturma olasılığını da keşfedebilirsiniz. https://the-trivia-api.com/api/questions?difficulty=hard