MVP паттерн

Хичээлээр анх IBM боловсруулан гаргасан Model View Presenter (MVP) - хэвийн талаар үзнэ. MVP нь MVC загвараас үүдэлтэй боловч програмын зохион байгуулалт талаасаа нилээд өөр хандлагатай. MVP паттерн MVC -г бодвол үзүүлбэр моделтой нягт холбоогүй байдаг онцлогтой. Доор зурагт MVP хэвийн бүтцийг харууллаа.

patt_04_01

Зургаас харахад контролерын оронд Presenter орж ирэн хэрэглэгчийн оруулсан өгөгдлийн шилжилт, загварын өөрчлөлтийг үзүүлбэрт тусгах үүргийг хариуцах болсон нь харагдана.

Presenter үзүүлбэртэй интерфейсээр дамжин харьцсанаар тестлэх боломжийг сайжруулна. Учир нь загварыг модулийн тестэд зориулагдсан тусгай загвараар сольж болно. MVP хэвийг MVC гийн адилаар програмын бизнес логик талаас авч үзцгээе.

patt_04_02

Бизнес логикийн талаас харвал MVP нь програмын бүхий л бизнес логикийг загварт багтаан харин өгөгдөлд хандалтын кодыг загвараас тусгаарласан нь MVC тэй адилхан. Энэ нь MVP нь MVC загвараас үүдэлтэйг батлана. MVP -д зөвхөн үзүүлбэрийн логик л өөр болсон.
Өмнөх хичээлүүдэд үзсэнтэй ижилхэн WPF програмын жишээг MVP паттернг ашиглан хийцгээе. Програмын бүтцийг дараах UML диаграмаар харууллаа.

patt_04_03

Үзүүлбэр IProjectsView интерфейсийг хэрэгжүүлэх ProjectsView классыг ашиглана. ProjectsView ба IProjectsView -д үзүүлбэрийг шинэчлэх, Presenter - тэй холбогдоход шаардлагатай бүхий л аргууд агуулагдана. Харин Presenter дотроо IProjectsView , IProjectsModel интерфейсийн төрлүүдийн холбоосыг ProjectsPresenter.view , ProjectsPresenter.model хэлбэрийн хувьсагч /шинж/ байдлаар агуулсан. Ийм зохион байгуулалт модел болон үзүүлбэрийн хоорондын харилцааг Presenter -ээр дамжуулан хийх боломжийг олгоно.
Бүтэц хэрхэн ажиллахыг тайлбарлая. Хэрвээ хэрэглэгч Update товчийг дарвал моделийг шинэчлэх ProjectsPresenter.view_ProjectUpdated() аргыг дуудах IProjectView.ProjectUpdated үйл явдлын боловсруулагч ажиллана. Загвар шинэчлэгдэх үед Presenter -ээр дамжин хэрэглэгчийн графикийн интерфейсийг шинэчлэх үйл явдлын IProjectsModel.ProjectUpdated боловсруулагч ажиллах юм. Эхэндээ загварын ажиллагааг ойлгоход хүндрэлтэй байж магадгүй. Түвшин хоорондын хамаарлыг бага болгохын тулд интерфейсийг хэрхэн ашиглаж байгааг сайн ойлгон аваарай. Ийм бүтцээр бичигдсэн програмыг цаашид хөгжүүлэх, кодыг ойлгоход цаг хугацаа, хүч хөдөлмөр хөнгөлдөг тул аргачлалыг өөрийн ажилдаа ашиглаж сурах хэрэгтэй. Бид үзүүлбэрийг үүсгэх логикийг Presenter -т шилжүүлсэн тул MVC загварыг бодвол тестлэх боломжоор хамаагүй илүү. MVC хэвд үзүүлбэрийг моделоос шууд үүсгэн өгдөг.
За одоо програмаа зохиоё. Програм MVC паттерн хичээлд үзсэнтэй яг адилхан ажиллана.

Модел

Visual StudioProjectBilling.UI.MVP нэртэй WPF шинэ төсөл үүсгээд Графикийн паттерн хичээлд үүсгэсэн ProjectBilling.DataAccess төслийн холбоосыг нэмэн өгөөрэй. Бид шинэ шийдэл /solution/ үүсгэсэн болохоор ProjectBilling.DataAccess төслийн холбоос үүсгэхийн тулд шийдэлд төслийг нэмэн оруулах хэрэгтэй. Үүний тулд шийдлийн нэр дээр баруун даралт хийхэд гарч ирэх цэснээс Add->Existing Project гэж ороод ProjectBilling.DataAccess төслийг заан өгнө. Төсөл шийдэлд нэмэгдсэний дараа ProjectBilling.UI.MVP төслийн Reference дээр баруун даралт хийгээд Add Reference цэсээр ороод доорх зурагт үзүүлснээр ProjectBilling.DataAccess төслийн холбоосыг нэмнэ.

patt_04_04

ProjectBilling.UI.MVP төсөлд дараах агуулга бүхий ProjectsModel классыг нэмнэ.

using System;
using System.Collections.Generic;
using System.Linq;
using ProjectBilling.DataAccess;

namespace ProjectBilling.Business
{
    #region ProjectsEventArgs

    public class ProjectEventArgs : EventArgs
    {
        public Project Project { get; set; }
        public ProjectEventArgs(Project project)
        {
            Project = project;
        }
    }

    #endregion ProjectsEventArgs

    public interface IProjectsModel
    {
        void UpdateProject(Project project);
        IEnumerable<Project> GetProjects();
        Project GetProject(int Id);
        event EventHandler<ProjectEventArgs> ProjectUpdated;
    }

    public class ProjectsModel : IProjectsModel
    {
        private IEnumerable<Project> projects = null;

        public event EventHandler<ProjectEventArgs>
            ProjectUpdated = delegate { };

        public ProjectsModel()
        {
            projects = new DataServiceStub().GetProjects();
        }

        public void UpdateProject(Project project)
        {
            ProjectUpdated(this,
                new ProjectEventArgs(project));
        }

        public IEnumerable<Project> GetProjects()
        {
            return projects;
        }


        public Project GetProject(int Id)
        {
            return projects.Where(p => p.ID == Id)
                .First() as Project;
        }
    }
}

Моделийн класс ProjectsModel доорх гишүүдтэй IProjectsModel интерфейсийг хэрэгжүүлж байгаа.

  • UpdateProject() арга төслийг шинэчлэнэ. Аргыг төлвөөр дамжуулан шинэчлэлийг хийж болохоор өргөжүүлж болох ч энд энгийн байлгах үүднээс үүнийг авч үзээгүй.
  • GetProjects() төслүүдийн жагсаалтыг авчирна.
  • GetProject() төслийг ID -гаар нь буцаана
  • ProjectUpdated төсөлд өөрчлөлт ороход дуудагдах үйл явдал.

ProjectEventArgs бол гишүүдийг нь үйл явдлын ProjectUpdated боловсруулагч ашиглаж болох туслах класс

Үзүүлбэр

Үзүүлбэрийг ProjectView.xaml , ProjectView.xaml.cs файлууд үүсгэнэ. Төсөлд үзүүлбэрийг нэмэхийн тулд төслийн нэр дээр баруун даралт хийхэд гарч ирэх цэснээс Add->Window гэж ороод үзүүлбэрийн нэрээ өгөхөд VS засварлагч .xaml, .cs өргөтгөлтэй файлуудыг төсөлд нэмэн оруулна. ProjectView.xaml файл дараах агуулгатай байна.

<Window x:Class="ProjectBilling.UI.MVP.ProjectsView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Төслүүд" MinHeight="265" Height="265"
        MinWidth="250" Width="250">
    <StackPanel>
        <Label Content="Төсөл:" Margin="5, 0, 5, 0" />
        <ComboBox Name="projectsComboBox" Margin="5, 0, 5, 0"
                SelectionChanged="projectsComboBox_SelectionChanged" />
        <Label Content="Нэр:" Margin="5, 0, 5, 0" />
        <TextBox Name="nameTextBox" Margin="5, 0, 5, 0"
                IsEnabled="False" />
        <Label Content="Тооцооны өртөг:" Margin="5, 0, 5, 0" />
        <TextBox Name="estimatedTextBox" Margin="5, 0, 5, 0"
                IsEnabled="False" />
        <Label Content="Гүйцэтгэлийн өртөг:" Margin="5, 0, 5, 0" />
        <TextBox Name="actualTextBox" Margin="5, 0, 5, 0"
                IsEnabled="False" />
        <Button Name="updateButton" Content="Update"
                Margin="5, 10, 5, 0" IsEnabled="False"
                Click="updateButton_Click" />
    </StackPanel>
</Window>

Формын кодыг үзүүлбэл

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ProjectBilling.Business;
using ProjectBilling.DataAccess;

namespace ProjectBilling.UI.MVP
{

    public interface IProjectsView
    #region IProjectsView
    {
        int NONE_SELECTED { get; }
        int SelectedProjectId { get; }
        void UpdateProject(Project project);
        void LoadProjects(IEnumerable<Project> projects);
        void UpdateDetails(Project project);
        void EnableControls(bool isEnabled);
        void SetEstimatedColor(Color? color);
        event EventHandler<ProjectEventArgs> ProjectUpdated;
        event EventHandler<ProjectEventArgs> DetailsUpdated;
        event EventHandler SelectionChanged;
    }

    #endregion IProjectsView

    #region ProjectsView


    public partial class ProjectsView : Window, IProjectsView
    {
        #region Initialization

        public int NONE_SELECTED { get { return -1; } }
        public event EventHandler<ProjectEventArgs>
        ProjectUpdated = delegate { };
        public int SelectedProjectId { get; private set; }

        public event EventHandler SelectionChanged
            = delegate { };
        public event EventHandler<ProjectEventArgs>
            DetailsUpdated = delegate { };

        public ProjectsView()
        {
            InitializeComponent();
            SelectedProjectId = NONE_SELECTED;
        }

        #endregion Initialization

        #region Event handlers

        private void updateButton_Click(object sender,
            RoutedEventArgs e)
        {
            Project project = new Project();
            project.Name = nameTextBox.Text;
            project.Estimate =
                GetDouble(estimatedTextBox.Text);
            project.Actual =
                GetDouble(actualTextBox.Text);
            project.ID =
                int.Parse(
                    projectsComboBox.SelectedValue.
                        ToString());
            ProjectUpdated(this,
                new ProjectEventArgs(project));
        }

        private void projectsComboBox_SelectionChanged(
            object sender, SelectionChangedEventArgs e)
        {
            SelectedProjectId
                = (projectsComboBox.SelectedValue == null)
                      ? NONE_SELECTED
                      : int.Parse(
                          projectsComboBox.SelectedValue.
                              ToString());
            SelectionChanged(this,
                new EventArgs());
        }

        #endregion Event handlers

        #region Public methods

        public void UpdateProject(Project project)
        {
            IEnumerable<Project> projects =
                projectsComboBox.ItemsSource as
                    IEnumerable<Project>;
            Project projectToUpdate =
                projects.Where(p => p.ID == project.ID)
                    .First() as Project;
            projectToUpdate.Name = project.Name;
            projectToUpdate.Estimate = project.Estimate;
            projectToUpdate.Actual = project.Actual;
            if (project.ID == SelectedProjectId)
                UpdateDetails(project);
        }

        public void LoadProjects(IEnumerable<Project> projects)
        {
            projectsComboBox.ItemsSource = projects;
            projectsComboBox.DisplayMemberPath = "Name";
            projectsComboBox.SelectedValuePath = "ID";
        }

        public void EnableControls(bool isEnabled)
        {
            estimatedTextBox.IsEnabled = isEnabled;
            actualTextBox.IsEnabled = isEnabled;
            updateButton.IsEnabled = isEnabled;
        }

        public void SetEstimatedColor(Color? color)
        {
            estimatedTextBox.Foreground
                = (color == null)
                      ? actualTextBox.Foreground
                      : new SolidColorBrush((Color)color);
        }

        public void UpdateDetails(Project project)
        {
            nameTextBox.Text = project.Name;
            estimatedTextBox.Text
                = project.Estimate.ToString();
            actualTextBox.Text
                = project.Actual.ToString();
            DetailsUpdated(this,
                new ProjectEventArgs(project));
        }

        #endregion Public methods

        #region Helpers

        private double GetDouble(string text)
        {
            return string.IsNullOrEmpty(text)
                ? 0 : double.Parse(text);
        }

        #endregion Helpers

    }

    #endregion ProjectsView
}

байна. Кодын бүтэц дээр үзүүлсэн UML диаграмтай тохирно.

Presenter

Presenter -ыг ердийн класс нэмэх байдлаар оруулна. Харин классын нэрийг ProjectsPresenter гэж өгөөд доорх агуулгыг оруулан өгөөрэй.

using System;
using System.Windows.Media;
using ProjectBilling.Business;
using ProjectBilling.DataAccess;

namespace ProjectBilling.UI.MVP
{
    public class ProjectsPresenter
    {
        #region Initialization

        private IProjectsView view = null;
        private IProjectsModel model = null;

        public ProjectsPresenter(IProjectsView projectsView,
            IProjectsModel projectsModel)
        {
            view = projectsView;
            view.ProjectUpdated += view_ProjectUpdated;
            view.SelectionChanged
                += view_SelectionChanged;
            view.DetailsUpdated += view_DetailsUpdated;
            model = projectsModel;
            model.ProjectUpdated += model_ProjectUpdated;
            view.LoadProjects(
                model.GetProjects());
        }

        #endregion Initialization

        #region Event handlers

        private void view_DetailsUpdated(object sender,
            ProjectEventArgs e)
        {
            SetEstimatedColor(e.Project);
        }

        private void view_SelectionChanged(object sender,
            EventArgs e)
        {
            int selectedId = view.SelectedProjectId;
            if (selectedId > view.NONE_SELECTED)
            {
                Project project =
                    model.GetProject(selectedId);
                view.EnableControls(true);
                view.UpdateDetails(project);
                SetEstimatedColor(project);
            }
            else
            {
                view.EnableControls(false);
            }
        }

        private void model_ProjectUpdated(object sender,
            ProjectEventArgs e)
        {
            view.UpdateProject(e.Project);
        }

        private void view_ProjectUpdated(object sender,
            ProjectEventArgs e)
        {
            model.UpdateProject(e.Project);
            SetEstimatedColor(e.Project);
        }

        #endregion Event handlers

        #region Helpers

        private void SetEstimatedColor(Project project)
        {
            if (project.ID == view.SelectedProjectId)
            {
                if (project.Actual <= 0)
                {
                    view.SetEstimatedColor(null);
                }
                else if (project.Actual
                         > project.Estimate)
                {
                    view.SetEstimatedColor(Colors.Red);
                }
                else
                {
                    view.SetEstimatedColor(Colors.Green);
                }
            }
        }

        #endregion Helpers
    }
}

Энд үйл явдлын дараах боловсруулагчдыг тодорхойлсон.

  • view_DetailsUpdated боловсруулагч IProjectsView.DetailsUpdated үйл явдлын хариу байдлаар дуудагдах бөгөөд төслийн гүйцэтгэлийн өртөгийг харуулах TextBox -ийн өнгийг шинэчлэх SetEstimateColor() аргыг дуудна.
  • view_SelectionChanged нь IProjectsView.SelectionChanged үйл явдал үүсэхэд үзүүлбэрийг өөрчилнө. Үйл явдал ComboBox -д шинэ төслийг сонгоход үүснэ.
  • model_ProjectUpdated боловсруулагч IProjectsModel.ProjectUpdate -ийн хариуд дуудагдан модел ба үзүүлбэрийн шинэчлэлтийг ажиллуулна.

Хэрвээ та хэвүүд ашиглан програм зохиож байгаагүй бол код ойлгомжгүй байж мэднэ. C# хэлний мэдлэгтэй бол энд бичсэн кодууд их энгийн учраас юу хийж байгааг ойлгоход амархан. Хамгийн гол зүйл бол паттерныг ашиглан програмын кодыг хэрхэн зохион байгуулж байгааг сурах юм. Хэвийг ОХП-ын ямарч хэлэнд ашиглаж болно.
Одоо програмын эхлэлийн цонх MainWindow.xaml -аас ProjectsView үзүүлбэрийг нээх боломжтой болгохын тулд MainWindow.xaml -д доорх өөрчлөлтийг оруулъя.

<Window x:Class="ProjectBilling.UI.MVP.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="250"
        MinHeight="250" MinWidth="250">
    <StackPanel>
        <Button Content="Төслийг үзүүлэх"
                Name="showProjectsButton" Margin="5, 10, 5, 0"
                Click="showProjectsButton_Click" />
    </StackPanel>
</Window>

Үндсэн цонхонд төслийн үзүүлбэрийг харуулах товч нэмсэн тул MainWindow.cs файлын агуулгыг доорх байдлаар өөрчлөөрэй.

using System.Windows;
using ProjectBilling.Business;

namespace ProjectBilling.UI.MVP
{
    public partial class MainWindow : Window
    {
        private IProjectsModel model = null;

        public MainWindow()
        {
            InitializeComponent();
            model = new ProjectsModel();
        }

        private void showProjectsButton_Click(object sender,
            RoutedEventArgs e)
        {
            ProjectsView view = new ProjectsView();
            ProjectsPresenter presenter
                = new ProjectsPresenter(view, model);
            view.Owner = this;
            view.Show();
        }
    }
}

Програмыг ажлуулбал MVC паттерн хичээлд хийсэн жишээтэй ижилхэн үр дүн гарч ирнэ. Энд MVP -д ашиглаж байгаа Presenter бүтэц л чухал. Танд ийм амархан зүйлийг хэтэрхий их ажил нэмэн хийгээд байгаа мэт санагдаж магадгүй. Сургалтын жишээнд л ингэж санагдана. Програм том хэмжээний олон асуудлыг шийдэх хэрэгтэй болоход хэвийн ач тус мэдрэгдэнэ. Хэвийн ерөнхий бүтцийг гаргах ажиллагаа нь таны програмын том жижгээс хамаарахгүй учраас л тэгж санагдаж байгаа юм. Цааш програмын хэмжээ томрох үед энэ загвараа ашиглаад явах болохоор асуудал багатай. MVC -тэй харьцуулбал MVP нилээд дэвшлийг авчирсан.

  • MVP нь Presenter -ээр дамжуулан төлвийн шалгалт, үзүүлбэрийн логикийг удирдах боломжийг өгсөн.
  • Үзүүлбэрийг моделоос бүрэн салгаж тэдгээрийн холбоог Presenter -ээр дамжуулан зохион байгуулсан.

MVP нь MVC гээс ялгаатай нь IView интерфейсийг ашигласнаар загварт шууд өөрчлөлт хийхгүйгээр бизнес логикийг дахин ашиглах боломжийг олгодог. Жишээ нь та энэ WPF програмыг Silverlight рүү шилжүүлэх хэрэгтэй болбол Silverlight дээр IProjectsView интерфейсийг хэрэгжүүлсэн үзүүлбэрийг л зохиох хэрэгтэй. Харин IProjectsPresenter, IProjectsModel интерфейсүүдийг өөрчлөлтгүйгээр дахин ашиглаж болно.        

Хичээлийг сайн судлаад ерөнхий санааг сайн ойлгож аваарай.

Мэдээлэл таалагдсан бол найзуудтайгаа хуваалцаарай.

  Нээгдсэн тоо: 13 Төлбөртэй

Давталт (Iterator) паттерн нийлмэл обьектын бүх элементүүдэд тэдгээрийн дотоод бүтцийг задлахгүйгээр хандах абстракт интерфейсийг тодорхойлдог. C# хэл дээр програм зохиогчид массив эсхүл коллекцийн обьектуудыг татан авдаг foreach циклтэй ажиллаж үзсэн байх. Энэ үед коллекцийн нийлмэл классуудад өөрийн бүтэц ба төлвөөрөө ялгаатай олонлог оршиж байдаг. Коллекцийг foreach -р гүйлгэн обьектуудыг авах боломжийг олгож байгаа түлхүүр хэрэгсэл бол давталт хэв буюу энгийнээр хэлбэл IEnumerable , IEnumerator хоёр интерфейс юм.

  Нээгдсэн тоо: 393 Бүртгүүлэх

C# хэл дээрх бүх програмийн код .cs өргөтгөлтэй файлд агуулагдана. Visual Studio -гоор үүсгэсэн төсөлд анхдагчаар Program.cs нэртэй нэг файл л үүснэ.  

Програмыг ажлуулахад анхдагчаар Program.cs файл ажилладаг. Шаардлагатай бол төсөлд C# -ийн бусад файлуудыг нэмж болно.

  Нээгдсэн тоо: 15 Нийтийн

Тодорхой нөхцөлд жишээ нь тоог тэгд хуваах гэх мэт тохиолдолд систем өөрөө онцгой нөхцлийн генерацийг хийдэг. Гэхдээ C# хэл throw оператороор онцгой нөхцлийг гараар үүсгэх боломжийг олгодог. Өөрөөр хэлбэл throw оператороор бид өөрсдөө онцгой нөхцлийг үүсгэн түүнийг програмийн ажиллагааны үед дуудаж болно гэсэн үг.

  Нээгдсэн тоо: 1726 Төлбөртэй

Task классыг ашиглан үүсгэсэн нэмэлт урсгалд үүссэн алдааг боловсруулах хичээлийн үргэлжлэлийг нийтэллээ. Өмнөх хичээлд цуцлалтын маркерыг ашиглан алдааг барихыг үзсэн. Энд анхаарах зүйл бас бий. Учир нь олон програм зохиогчид ялангуяа эхлэн суралцагчид цуцлалтын маркерыг тийм ч зөв ашиглаад байдаггүй. Бид Task классын Status шинжид RanToCompletion , Cancelled , Faulted гэсэн үндсэн гурван утгууд байдагийг судлан тогтоосон.

Цэсийг нээх хаах ажиллагааг хариуцах компонентийг боловсруулсан тул энэ хичээлээр програмийн удирдах цэсийг…

Нээгдсэн тоо : 6

 

Математикийн үйлдлүүдэд нэг ба тэг тоонууд онцгой шинжүүдтэй. Үржих үйлдэлд нэг ба тэг

Нээгдсэн тоо : 10

 

Давталт (Iterator) паттерн нийлмэл обьектын бүх элементүүдэд тэдгээрийн дотоод бүтцийг задлахгүйгээр хандах абстракт интерфейсийг тодорхойлдог. C# хэл дээр…

Нээгдсэн тоо : 13

 

Тодорхой нөхцөлд жишээ нь тоог тэгд хуваах гэх мэт тохиолдолд систем өөрөө онцгой нөхцлийн генерацийг хийдэг. Гэхдээ C#

Нээгдсэн тоо : 15

 

Програмийг удирдах цэсийг нээх болон хаах ажиллагааг хариуцах компонентийг боловсруулъя. Үүний тулд төслийн components хавтаст Navigation хавтасыг үүсгээд…

Нээгдсэн тоо : 17

 

Арифметикийн үндсэн 4 үйлдлийн нэг бол үржих. Нэмэх , хасах үйлдлийн талаар…

Нээгдсэн тоо : 14

 

Шаблоны арга (Template Method) хэв дэд классуудад алгоритмын бүтцийг өөрчлөхгүйгээр зарим алхамуудыг дахин тодорхойлох боломж олгосон ерөнхий алгоритмыг…

Нээгдсэн тоо : 17

 

Гурвалжны медиантай холбоотой бодлогууд шалгалт шүүлэгт ихээр орж ирдэг. Иймээс гурвалжны медиан, түүний шинжүүдийг бүрэн мэддэг байх хэрэгтэй.

Нээгдсэн тоо : 23

 

Бүх онцгой нөхцлүүдийн суурь бол Exception төрөл. Төрөлд онцгой нөхцлийн талаарх мэдээллийг авч болох хэдэн шинжийг тодорхойлсон байдаг.…

Нээгдсэн тоо : 23

 
Энэ долоо хоногт

илэрхийллийг хялбарчил

Нээгдсэн тоо : 996

 

ABCD трапецийн бага диагонал BD=6 бөгөөд суурьтай перпендикуляр. Трапецийн AD=3, DC=12 бол B, D мохоо өнцгийн нийлбэрийг ол.

Нээгдсэн тоо : 2220

 

Геометрийн шалгалтанд сурагчид шалгалтын асуултуудаас нэг асуулт ирнэ. Сурагч "Дотоод өнцөг" сэдвийн асуултуудад хариулах магадлал 0,35 харин "Багтаасан тойрог" сэдвийн асуултуудад хариулах ммагадлал 0,2 байжээ. Шалгалтын асуултуудад энэ хоёр сэдэвт хоёуланд зэрэг хамаарах асуулт байхгүй бол сурагчид энэ хоёр сэдвийн аль нэгэнд нь хамааралтай асуулт ирэх магадлалыг ол.

Нээгдсэн тоо : 550