0

私は 9 ユニットのクラスを教えています。生徒は各ユニットに「合格」、「メリット」、または「優等」で合格することができます。AP は 70 ポイント、M は 80 ポイント、D は 90 ポイントを獲得します。年間の総合結果は、すべてのユニットのポイントの合計です。

「M」基準が許可される前にすべての「P」基準に合格する必要があり、「D」基準が許可される前にすべての「M」基準に合格する必要があります。P/M/D 基準の数は、ユニットによって異なります。次の学生は、すべての D 基準を取得したにもかかわらず、M に失敗したため、このユニットの「合格」(70 点) を達成しました。

ユニット 1 - 脳外科

P1 - 脳がどこにある
かを知る - P2 に合格 - どちらが上にあるのかを知る -
M1 に合格 - 脳が何をするかを説明する -
M2 に合格 - 男性と女性の脳に違いはありますか - 不合格
D1 - なぜ私の脳ができるのかを理解してくださいこれを解決する -
D2 に合格する - 脳が論理を即座に理解できるようにする薬を発明する -
D3 に合格する - 頭脳の力だけで大金を稼ぐ方法を見つける - 合格する

これらの列で DataTable を埋める SqlDataReader があります。クエリはすでに個々の学生によって選択されているため、DataTable には 1 人の学生のレコードのみが含まれています。次のようになります。

UnitNo   Citerion   Type   passed?  
1        know etc     P       Yes  
1        know etc     P       Yes  
1        explain etc  M       Yes  
1        is there etc M       No  
1        Figure etc   D       Yes  
1        invent etc   D       Yes  
1        find etc     D       Yes  
2        blah etc     P       Yes  
2        wot etc      P       Yes  
2        so etc       M       No 

そして、私は次のような DataTable を求めています。

UnitNo  P    M   D   Points  
1       Y    N   Y     70  
2       Y    Y   N     80  
3       N    N   N      0  
4       N    Y   Y      0  
5       Y    Y   Y     90  

…………………………
_
_

最後にポイントを合計します - 学生は 240 ポイントを持っています。

私は DataTables や c# などでまったく問題ありません。それは、私がやっている爆破されたロジックです。私が書いたコードのすべてのビットは、約 2 行後にスパゲッティのように見えます。

このロジックを整理するための指針を持っている人はいますか? ゴーメンガストの学校のシーンのようなものです... あなたがそれを解決することができれば、私は個人的に妻を送り、あなたにサンデーローストを調理させます.

パソコン


OK、これはCSharperの回答が組み込まれた実際のコードです(追加の列名のソリューションを追加するために編集されています)。それは明らかに正しい解決策です。数字が表示されないだけです (DataRow キャストの後に括弧が省略されているのを見つけましたが、それは問題ではありません)。結果を表示するために、最後にいくつかのテスト グリッドを接続しました。また、私はlinqの人ではないので、最初のテーブルから2番目のテーブルにユニット名を追加する方法、またはポイントを合計する方法がわかりません:

(注: passFail フィールドで 1 = マークなし、2 = 不合格、3 = 合格を使用しています)

//create the sql to extract the data
        String sqlString = "SELECT unitNo, unitName, criterionPMD, passFail FROM unitDetails INNER JOIN unitStudentRecord ON unitDetails.id = unitStudentRecord.unitDetailsId INNER JOIN unitSummary ON unitDetails.unitSummaryId = unitSummary.id WHERE studentID = '" + ((String)Session["studentID"]).Trim() + "'";
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["studentTutorialsConnectionString"].ConnectionString);
        SqlCommand sqlComm = new SqlCommand(sqlString, conn);
        conn.Open();
        SqlDataReader sqlTotalMarks = sqlComm.ExecuteReader();

        //create the workings out datatable and fill it
        DataTable dtWorkings = new DataTable();
        dtWorkings.Load(sqlTotalMarks);
        conn.Close();

        // create the results datatable
        DataTable dtResults = new DataTable();
        dtResults.Columns.Add("units", typeof(int));
        dtResults.Columns.Add("name", typeof(string));
        dtResults.Columns.Add("P", typeof(bool));
        dtResults.Columns.Add("M", typeof(bool));
        dtResults.Columns.Add("D", typeof(bool));
        dtResults.Columns.Add("points", typeof(int));

        //fill the results table
        foreach (var units in dtWorkings.Rows.Cast<DataRow>().GroupBy(r => r["unitNo"]))
        {
            var p = units.Where(r => r["criterionPMD"] == "P").All(r => r["passFail"] == "3");
            var m = units.Where(r => r["criterionPMD"] == "M").All(r => r["passFail"] == "3");
            var d = units.Where(r => r["criterionPMD"] == "D").All(r => r["passFail"] == "3");
            dtResults.Rows.Add(
                 units.Key,//UnitNo
                 units.Select(r => r["unitName"]).First(),//UnitName                    
                 p,
                 m,
                 d,
                 p ? (m ? (d ? 90 : 80) : 70) : 0);//Points
        }

        gvTemp.DataSource = dtWorkings;
        gvTemp.DataBind();
        gvSummary.DataSource = dtResults;
        gvSummary.DataBind();

gvTemp のグリッドは次のとおりです。

   unitNo   unitName       criterionPMD passFail
    2     Computer systems  P     3
    2     Computer systems  P     1
    3     Web rubbish           P     3

gvSummary のグリッドは次のとおりです。

units   name               P     M  D   points
2           Computer systems            90   
3           Web rubbish                             90

gvSummary グリッドでは、すべての PMD 基準に対してチェックボックスが表示されますが、合計は表示されません。2号機は0点、3号機は70点と予想していたのですが…

めちゃめちゃ近い…

4

1 に答える 1

1

C# クラスでこれを行うと、問題をより小さな部分に構造化し、より保守しやすいソリューションを得るのに役立つ場合があります。ただし、確かにそれも可能DataTableです。データ テーブルのもう 1 つの欠点は、データがタイプ セーフに実装されにくいことです。この回答の最初のバージョンでは、文字列への r["criterionPMD"] のキャストが欠落していたため、文字列比較の代わりに参照比較がありました。

            //create the workings out datatable and fill it
            DataTable dtWorkings = new DataTable();
            dtWorkings.Columns.Add("unitNo", typeof(int));
            dtWorkings.Columns.Add("unitName", typeof(string));
            dtWorkings.Columns.Add("criterionPMD", typeof(string));
            dtWorkings.Columns.Add("passFail", typeof(int));

            dtWorkings.Rows.Add(2, "Computer systems", "P", 3);
            dtWorkings.Rows.Add(2, "Computer systems", "P", 2);
            dtWorkings.Rows.Add(3, "Web rubbish", "P", 3);

            // create the results datatable
            DataTable dtResults = new DataTable();
            dtResults.Columns.Add("units", typeof(int));
            dtResults.Columns.Add("name", typeof(string));
            dtResults.Columns.Add("P", typeof(bool));
            dtResults.Columns.Add("M", typeof(bool));
            dtResults.Columns.Add("D", typeof(bool));
            dtResults.Columns.Add("points", typeof(int));

            //fill the results table
            foreach (var units in dtWorkings.Rows.Cast().GroupBy(r => r["unitNo"]))
            {
                var p = units.Where(r => (string)r["criterionPMD"] == "P").All(r => (int)r["passFail"] == 3);
                var m = units.Where(r => (string)r["criterionPMD"] == "M").All(r => (int)r["passFail"] == 3);
                var d = units.Where(r => (string)r["criterionPMD"] == "D").All(r => (int)r["passFail"] == 3);
                dtResults.Rows.Add(
                     units.Key,//UnitNo
                     units.Select(r => r["unitName"]).First(),//UnitName                    
                     p,
                     m,
                     d,
                     p ? (m ? (d ? 90 : 80) : 70) : 0);//Points
            }

複雑な条件式を使用すると、p、m、および d のすべての基準が満たされた場合にのみ 90 ポイントが与えられることが保証されます。

これにより、合格と識別基準のみのユニットでも正しい結果が得られるため、90、70、または 0 ポイントのみが可能です。それがあなたの要件かどうかはわかりません。

「P」基準のみを使用した例では、70 ポイントまたは 90 ポイントが正しい結果であるかどうかを判断するのは困難です。このコード スニペットは、すべての P、M、および D 基準が満たされているかどうかをチェックし、この場合、M または D 基準がなく、すべての P 基準に合格した場合でも、90 ポイントを与えます。現実世界のすべてのシナリオでは、このエッジケースはないと思いますが、とにかくこれについて考える価値があります.

于 2013-01-06T14:35:40.880 に答える