package org.broad.igv.sam;

import org.junit.Test;

import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;

public class BaseModificationsTest {

    @Test
    public void testOrientTopFwd() {

        //top-fwd	0	*	0	0	*	*	0	0	AGGATCTCTAGCGGATCGGCGGGGGATATGCCATAT	*	Mm:Z:C+m,1,3,0;	Ml:B:C,128,153,179
        byte[] sequence = "AGGATCTCTAGCGGATCGGCGGGGGATATGCCATAT".getBytes();
        String mm = "C+m,1,3,0";
        byte[] ml = {(byte) 128, (byte) 153, (byte) 179};
        boolean isNegativeStrand = false;
        int[] expectedPositions = {7, 30, 31};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        assertEquals(expectedPositions.length, mods.size());
        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals('C', sequence[mod.position]);
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(ml[i], mod.likelihood);
        }
    }

    @Test
    public void testOrientTopRev() {

        //                                          ....45..........6.......4...8.0.....
        //top-rev	16	*	0	0	*	*	0	0	ATATGGCATATCCCCCGCCGATCCGCTAGAGATCCT	*	Mm:Z:C+m,1,3,0;	Ml:B:C,128,153,179
        byte[] sequence = "ATATGGCATATCCCCCGCCGATCCGCTAGAGATCCT".getBytes();
        String mm = "C+m,1,3,0";
        byte[] ml = {(byte) 128, (byte) 153, (byte) 179};
        boolean isNegativeStrand = true;
        int[] expectedPositions = {28, 5, 4};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        assertEquals(expectedPositions.length, mods.size());
        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals('G', sequence[mod.position]);    // Reverse strand - G is complement of C
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(ml[i], mod.likelihood);
        }
    }


    @Test
    public void testOrientBotFwd() {
        //                                                    1         2
        //                                          .12.......0.12...78.01234....9......
        //bot-fwd	0	*	0	0	*	*	0	0	AGGATCTCTAGCGGATCGGCGGGGGATATGCCATAT	*	Mm:Z:G-m,0,0,4,3;	Ml:B:C,115,141,166,192

        byte[] sequence = "AGGATCTCTAGCGGATCGGCGGGGGATATGCCATAT".getBytes();
        String mm = "G-m,0,0,4,3;";
        byte[] ml = {(byte) 115, (byte) 141, (byte) 166, (byte) 192};
        boolean isNegativeStrand = false;
        int[] expectedPositions = {1, 2, 18, 23};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        assertEquals(expectedPositions.length, mods.size());
        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals('G', sequence[mod.position]);
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(ml[i], mod.likelihood);
        }
    }

    @Test
    public void testOrientBotRev() {

        //                                          ......6....12345.78...23.5.......34.
        //bot-rev	16	*	0	0	*	*	0	0	ATATGGCATATCCCCCGCCGATCCGCTAGAGATCCT	*	Mm:Z:G-m,0,0,4,3;	Ml:B:C,115,141,166,192
        byte[] sequence = "ATATGGCATATCCCCCGCCGATCCGCTAGAGATCCT".getBytes();
        String mm = "G-m,0,0,4,3;";
        byte[] ml = {(byte) 115, (byte) 141, (byte) 166, (byte) 192};
        boolean isNegativeStrand = true;
        int[] expectedPositions = {34, 33, 17, 12};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        assertEquals(expectedPositions.length, mods.size());
        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals('C', sequence[mod.position]);    // reverse strand, complement
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(ml[i], mod.likelihood);
        }
    }

    @Test
    public void testChebi() {
        // @CO	Separate m, h and N modifications
        //                                                    1         2         3
        //                                          ..2.4.67.....3...7.90...4.5.8.01.34.
        //        *	0	*	0	0	*	*	0	0	AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA	*	Mm:Z:C+m,2,2,1,4,1;C+76792,6,7;N+n,15;	Ml:B:C,102,128,153,179,204,161,187,212,169
        byte[] sequence = "AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA".getBytes();
        String mm = "C+m,2,2,1,4,1;C+76792,6,7;N+n,15;";
        byte[] ml = {(byte) 102, (byte) 128, (byte) 153, (byte) 179, (byte) 204, (byte) 161, (byte) 187, (byte) 212, (byte) 169};
        boolean isNegativeStrand = false;

        String[] expectedModifications = {"m", "m", "m", "m", "m", "76792", "76792", "n"};
        int[] expectedPositions = {6, 17, 20, 31, 34, 19, 34, 15};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(expectedModifications[i], mod.modification);
            assertEquals(ml[i], mod.likelihood);
        }
    }

    @Test
    public void testDouble() {
        //public static void main(String [] args) {
        // @CO	Modifications called on both strands of the same record,
        // @CO	including potentially at the same location simultaneously.
        //                                                1         2         3
        //                                      .....5.7...1....6..9..........01....
        // *	0	*	0	0	*	*	0	0	AGGATCTCTAGCGGATCGGCGGGGGATATGCCATAT	*	Mm:Z:C+m,1,3,0;G-m,0,2,0,4;G+o,4;	Ml:B:C,128,153,179,115,141,166,192,102
        //                                      .12.......0.23...78.01234....9......

        byte[] sequence = "AGGATCTCTAGCGGATCGGCGGGGGATATGCCATAT".getBytes();
        String mm = "C+m,1,3,0;G-m,0,2,0,4;G+o,4";
        byte[] ml = {(byte) 128, (byte) 153, (byte) 179, (byte) 115, (byte) 141, (byte) 166, (byte) 192, (byte) 102};
        boolean isNegativeStrand = false;
        String[] expectedModifications = {"m", "m", "m", "m", "m", "m", "m", "o"};
        int[] expectedPositions = {7, 30, 31, 1, 12, 13, 22, 13};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(expectedModifications[i], mod.modification);
            assertEquals(ml[i], mod.likelihood);
        }
    }

    @Test
    public void testMulti1() {
        // @CO	Testing multiple m, h and N modifications on the same read.
        // @CO	r1 has them separated out.
        // @CO	r2 has them combined together, for example as produced by
        // @CO	a joint basecaller which assigns probabilities to all
        //  @CO	trained events simultaneously.
        //                                                1         2          3
        //                                      ..2.4.67.....3...7.90...4.6.8.01.34.
        // r1	0	*	0	0	*	*	0	0	AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA	*	Mm:Z:C+m,2,2,1,4,1;C+h,6,7;N+n,15,2;	Ml:B:C,128,153,179,204,230,159,6,215,240

        byte[] sequence = "AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA".getBytes();
        String mm = "C+m,2,2,1,4,1;C+h,6,7;N+n,15,2";
        byte[] ml = {(byte) 128, (byte) 153, (byte) 179, (byte) 204, (byte) 230, (byte) 159, (byte) 6, (byte) 215, (byte) 240};
        boolean isNegativeStrand = false;
        String[] expectedModifications = {"m", "m", "m", "m", "m", "h", "h", "n", "n"};
        int[] expectedPositions = {6, 17, 20, 31, 34, 19, 34, 15, 18};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(expectedModifications[i], mod.modification);
            assertEquals(ml[i], mod.likelihood);
        }
    }

    @Test
    public void testMulti2() {
        // @CO	Testing multiple m, h and N modifications on the same read.
        // @CO	r1 has them separated out.
        // @CO	r2 has them combined together, for example as produced by
        // @CO	a joint basecaller which assigns probabilities to all
        //  @CO	trained events simultaneously.
        //                                                1         2          3
        //                                      ..2.4.67.....3...7.90...4.6.8.01.34.
        // r2	0	*	0	0	*	*	0	0	AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA	*	Mm:Z:C+mh,2,2,0,0,4,1;N+n,15;	Ml:B:C,77,159,103,133,128,108,154,82,179,57,204,31,240

        byte[] sequence = "AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA".getBytes();
        String mm = "C+mh,2,2,0,0,4,1;N+n,15";
        byte[] ml = {(byte) 77, (byte) 159, (byte) 103, (byte) 133, (byte) 128, (byte) 108, (byte) 154, (byte) 82, (byte) 179, (byte) 57, (byte) 204, (byte) 31, (byte) 240};
        boolean isNegativeStrand = false;

        String[] expectedModifications = {"m", "h", "m", "h", "m", "h", "m", "h", "m", "h", "m", "h", "n"};
        int[] expectedPositions = {6, 6, 17, 17, 19, 19, 20, 20, 31, 31, 34, 34, 15};

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, isNegativeStrand);

        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            System.out.println(mod.position);
            assertEquals(expectedPositions[i], mod.position);
            assertEquals(expectedModifications[i], mod.modification);
            assertEquals(ml[i], mod.likelihood);
        }

    }

    @Test
    public void testONTForwardAlignment() {
        byte[] sequence = "GTGTAGCTGGTTCAGTTACATTATTGCTCACTGCAGCCTCCGCCTCCTGGGTTCAAGTGATTCTTCTTGCCTCAGCCTCCCAAGTAGCTGGGATTACAGGCGCCCGCCACTACCCGGCTAATTTTTGTATTTTTAGTAGAGACAGGGTTTCACCATGTTAGCCAGGATGGTCATGATCTCTTCCTGACCTCATGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGTGTGAGCCACTGCACCAGAAAACAAGAGTGAATTTTAAAAAACAGTGCAGCAGGGCCGGGCTCCGTGGCTCACATCTGTAATCCCAGCACTTTGGGAGGCAAAGCCGGGCAGTTCGTTGGAGGTCGGAGTTCAGGAGACCAGCCCGGGCAACATGGTGAAACCCCGTCTCGACTAAAAATACTAAAAATTAGGCCAGGTGCAGTGGCTCACTGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGAGGGCGCTTGAGGTCAGGAGATGAGACCATCCTGACCAACATGGCAAGACCCATCTTAAAAACACACACTCTTAAAGCAGGTTTGTGTTTGGCACCAGTAGATCAGTCCTCAGGAGGCTGAGGCGAAAGTCAACAGGTGAGGGAGTTACGGTGTCGAGACAGGCCACTGCACTTCCAGCCTGGGTGAGTTAGAAGACCTGTCTCAACAAAAATTAATAAAAATTAGCTGGGTGTGAGTGCACGTACACTTGGGAGGCTGAGGCAGCAGAATCATTTAAACCTGGGAGGCAGGGGGTTGTAGTAGAAGCCAAGATCGTGACACCGTACCAGCCTGGGTGACAGAGAAAGACCCCATCTCAAAAAAAACAGAAAACAAAAAACAAAACAAACAAAAAAACTAAATATCTTTGTAGCCCACAGGCTATCCATTTTATTCAAAGCATCAAGAAGTAAGAAAATGAAGAAAGGGCTCTGTGTTGCCCATAGGTGGGTGGGATTGCAATAACTCGAGAAGCATCAGTGAGGCTTTCAGGCAGGAGGCTCTCACTCCCTCTGTCAGTCATCTTGGAGATGTCCAGAGGCTAAGATGCCCAGCCATACAGAGGTGGTGAGAACCATCGTGGCGGCTCCAGGAGAAGAGGCCCAGAAATGGACATTTGAATGATTGAAACTGCCTAAAGCACTCCTGCAACAAAGCACTCCATGTCTCACATTGACATGGAACAATTAACTGAAATGGGAAACATATCAACTCAGGCTGCCTCCCTCTGTTTCAGACCAGTGTTCTACTCTACACAGCAAACCAGGTCTCCCTTTCTTTCCTGCCTGCAGTCATTCCCAGAAGTTTACCTCAAAGGAACTCATGTTTCTGAAAATCCAGTTTGGGCATGGGCTCTCAATGCCTTCTGGCTCCCTCTCTGAATTTCATAATCTGATATAGAAAATAGTAGCTCACATTTCTGACACTCTGTATGGAGAGATGTGTAGCATGGCTCGCCTCTCCATGAACGTCAGTGACCCTGAGATTTGGATCTTTGCCCTTCACATTTCTATATTCAGGAGCTGGCTCCATGCAATTTGGACTCTACCCCTAATAAGTCAGGGACATGAACCCCAAATTCTAAACACTTGGACCTCCAGAATCACCACCTGGATTCATTCCTGTCCAAATAAATGACTGTGGCCAGTATGTGTGTGTGCTATATTTATAAAGCACTTTTGATGTTAGGTTTATTTAAGCTTCACAATTCTTCAGTGAGGTAGGAAATAATCCCATTTTATGGAGGGAAAAGCTGAGATTTGGAAAAGTTATCCCCCAAAGTTACACAGCTACTAAGGGACAGAGCTGGACTTCAAATCAAGTTGTTTGATCTAAACTCAGTGCATGTCCACCATTTCATCCTACCTTTTGATTACGGTTGACATTATAAATTAAATACATGTCCCTAAGTGGATTTTTAAGTAAGCAAATAAGATCTCTTCCTACCTAAGCACCTAGCACATTAGCTGGAGAACTAGCACAAAGCGAAGCCACACAGATTGTTACCAACTCAGCTCTCTCCCAATGGATGCATGAGTTTAAAGGATATTAAAGTTACCAATTATGGAACTCATTCTAGGTGCCAGGCCCTGTGCCAGTCTCTTTACATCCATTATCACTTAATCTTAATATCAGTTATTTCAAGATAGGCATTATTCTTCCACTGGGAAACTGAGGCTCAAGAAGTCAAATATTGGCTGGGTGTGGTGGCTCATGCCTGCAATCCCAGCACTTTGGGAGGATCACTTGAGGTCAGGAGTTTGAGACCAGCCTGGCCAACATGGTGAAACCCCATCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCAGGCATCTGTAATCCCAGTTATTCAGGAGGCTGAGGCAGGAGAATCACCTGAACCCGGGAGGCAGAGGTTCAGTGAGTCGAGATCTTGCCACTGCACTCCAGCCTGGGAGACAGAGGGAAATTCGTCTCAAAAAAAAAAAAGAAAAGAAAAGTAGAAGACGAAGATGAAGAAGAATAAGAAGAGAGAAAGAAGAGAGGTTAGAGAAAAGAAGGAGAAGGAGAAGGAGGAGGAGAAGGAGAAGGAGAAGAAGAAGAAGAAGAAGAAGAAGGAAGAAGAAGAAGAAGAAGAGTCAATATCTGGAGAAGAAGAAAGAGAGGAAGAAGAAGAAGAGGAAGAAGAAGAAGAAGGGAAGGAAGAAAGAGAAGAAGAACAGAAGAAAGAGGGAGTCAAATATCTGGAGAAGGGAGGAAGAAAGAAGAAAGAAGAAAGAGGAGGAGGAAGAAGAAGAAGAAGAAGAAGAAGCAGGAGCAGGAGAAGAGAAGAAGAAGAAGAGAGAGGGAAGAGGGAAGGAAGAGGAGAGGAAGAGAGAGAAAGAAGAAGAAGAAAGAAGAAGAAAGAAGAAAGAAAGAAAGAAAGAAGAAGAAAGAAGAAAGAAGAAGAAGAAAGAAGAAAAGACAAATATCTGGAGCCAGGATTTGAGCCTGGCCCTTGACATATAATGCAAGAGCCTCACCACACTCTCCTTACCAGCCCCTGTCCTTAGGCCTGGGCCCCTGATTGCCTTGTCAGAGAAGCCAGAGAATCTGGGCCTTTTTAGCTTTTATCCTAGGAGGCTGGAATAATCTCCTTCTAAGGGGTACTAAGGGGACGCCCAGGGAGAACAGGGGTTCTGATGAGGGTGGAGGGAGAGGGGTGTGATGCTGTACTGGCTTTGTTCACTAACACAGCTACTAAGGGAGCTTTGAGAGAGAGGCCTCTCAGTGAAGAGCCCGGGTCAACCCCCATTTCCCTCGTTCAGGTACGACATACCCTGGGAAGCCTTGACTCATTAGGGCTCCAGAGTCTCTAACTGTGCAGCAGGG".getBytes();
        String mm = "C+m,10,17,2,5,16,2,2,18,2,11,1,0,5,5,18,0,0,27,0,2,2,15,11,2,35,27,95,5,88,21,92,17,59,21,9,1;C+h;";
        byte[] ml = null;  // not testing for this
        String cigar = "25S38M1I48M2D69M3I64M1I2M1I11M2D2M1D14M1D1M2I3M1D74M1D7M2I49M1I27M1I31M2I7M3D16M1D22M1D12M4D15M1D10M1I7M2D2M1D10M1I1M2D3M1D18M2D7M5D10M2D3M1D8M2D8M1D11M1I11M1D1M2D9M4I7M9D31M1I3M1I49M1I12M2I22M2D41M1I6M1I31M1I21M1D16M1I18M1I12M1I9M1D10M2D10M1I14M2I17M2D43M2D15M2D18M3D73M1D8M2D63M1D8M3D8M1I23M7D65M1I3M5I6M2D4M1D4M1I6M1D4M3D9M1D3M1D9M2I2M1D4M2I6M1D2M3I4M1I2M1I17M1I4M5I7M1D23M1I5M1I4M1I24M4D15M1D2M2I21M4I2M1D48M1I6M1D141M1I27M1I45M1D13M1D65M2D11M1D72M1D7M3D34M1D9M2D2M1D6M3D13M1D66M2D25M1I19M10D242M1D53M1D21M1D43M4D8M1D17M4D56M1I17M2I4M1D10M15I27M6I8M3I9M2I2M1I12M2I3M5I6M2I7M1I6M1I6M2D5M3D3M1I34M1I8M1I13M1I8M5I14M5I2M1I3M1I12M1I9M1I6M5I3M1I3M1I9M1I6M1I12M1I54M1I7M1I5M1I25M1D20M1D5M1I27M1I42M1D10M1D7M1D13M1I15M1D4M1I59M2I39M1I62M15S";

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, false);

        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            int p = mod.position;
            assertEquals('C', sequence[p]);
        }
    }

    @Test
    public void testONTNegativeAlignment() {
        byte[] sequence = "[encoded data, 11800 characters]".getBytes();
        String mm = "C+m,139,16,5,60,507,349,11,24,0,10,5,18,2,8,9,7,2,30,1,2,3,10,2,0,7,59,4,96,14,15,8,8,55,56,88,100,49,5,16,46,4,31,53,101,8,52,24,104,5;C+h;";
        byte[] ml = null; // not testing for this
        String cigar = "14S20M1I21M2D18M1D18M1D36M3D31M1D7M1D5M4I27M4D6M1D10M1I36M1D14M1I15M1D10M1D37M2I17M2D35M1I1M2I5M4I65M1D64M4I10M1D6M1D42M1D14M1D21M1I25M2I17M4D6M2D20M4D18M2D17M2D20M1D4M1D14M1I11M1D12M2I2M6D14M1D4M4D11M1I3M1D56M1D12M1I34M1D17M1D6M1D43M1D11M1D15M1D30M1D9M1I11M1D73M1D18M1D7M2I9M4I7M3I12M2D4M2I3M1D11M2I8M1D10M1D9M1D10M1D3M2D4M1D29M3D23M4I15M1D23M2I22M2D33M1D4M1D54M2D8M1D9M3D12M3D14M1I22M1D25M1I36M1D10M3D7M2I3M2I6M1I17M1I4M1I21M1I49M1D32M1D59M1I6M1I50M1I33M1I7M1I5M1D14M1D9M1I5M2D18M1D51M1D14M1D8M2I3M...25M5I4M1I5M2I30M3I1M1I56M3I98M4D13M3I20M2I32M49I96M1D5M1D14M2I30M1D71M1I11M1D23M1I37M1I8M1I10M2D12M2D16M1D10M1I33M1D29M1D4M2I9M1I18M1D39M2D91M2D10M1I14M1I5M1D12M1I35M1D1M1D40M2D28M1D3M1I5M1I10M2D17M1D24M3D1M1D62M1D6M1D33M1D3M1D12M1D8M1I13M1I2M1I41M1D19M1D85M2D35M1I19M4I4M3I3M1I6M1I2M1I10M9D24M2D1M1D23M2D18M1D18M1I34M3D13M1I44M1I11M1I31M2D58M1I14M1I4M1D30M1D24M1D28M1D41M1D50M1I8M1D13M2I3M1I73M2D43M2I16M1D23M2I55M1I21M1I16M1D61M1D19M1D20M1D13M1I43M1D28M1D48M1D17M2I71M1D8M2D3M5I11M1I8M1D8M2D49M26S";

        List<BaseModification> mods = BaseModification.getBaseModifications(mm, ml, sequence, true);

        for (int i = 0; i < mods.size(); i++) {
            BaseModification mod = mods.get(i);
            int p = mod.position;
            assertEquals('G', sequence[p]);
        }
    }

//
//    public static void main(String[] args) {
//        byte[] origSequence = "[encoded data, 20474 characters]".getBytes();
//        byte[] sequence =     "[encoded data, 20474 characters]".getBytes();
//        int[] deltas = {37,3,844,39,6,7,27,53,19,13,2,8,0,31,3,1,1,0,4,11,11,2,14,27,129,406,5,25,234,13,12,51,362,102,445,145,13,19,6,2,121,9,4,32,33,54,100,7,5,105,10,22,0,1,10,4,2,9,2,38,9,31,31,101,305,29,26,5,125,1,1,6,39,5};
//
//        int dIDX = 0;
//        int delta = deltas[0];
//        int matchCount = 0;
//        int match = (byte) 'C';
//
//        System.out.println("delta length = " + deltas.length);
//        for(int s=0; s<sequence.length; s++) {
//            if(sequence[s] == match) {
//                if(delta == matchCount) {
//                    System.out.println(dIDX + " " + s);
//                    matchCount = 0;
//                    dIDX++;
//                    delta = deltas[dIDX];
//                } else {
//                    matchCount++;
//                }
//            }
//        }
//
//        int sumDeltas = 0;
//        for(int d : deltas) sumDeltas += d;
//        System.out.println("Required = " + (sumDeltas + deltas.length));
//
//        int sumGs = 0;
//        for(byte c : origSequence)  {
//            char ch = (char) c;
//            if(ch == 'G') sumGs++;
//        }
//        System.out.println("Actual = " + sumGs);
//    }
}