As soon as the Thistlegorm Wreck loomed into view, I was in my element and it instantly went to the top of my "best wreck diving" experiences. It is such a large ship that you could dive there numerous times without needing to explore the same passageway or hold again.
Resting at an easily accessible depth of 15m it felt like a visit to a World War II museum. The storage hold was crammed with machine guns, rifles and boxes of ammunition. There were old BSA motorbikes, armoured vehicles and trucks, all reminders of the bitter war taking place when HMS Thistlegorm was bombed in 1941.
During the 7 night "North & Wrecks" cruise we traversed a circular route from Hurghada in Egypt through a glut of diving wrecks of all shapes and sizes. Among them were the 4 well-known Abu Nuhas wrecks near Shadwan Island, the Dunraven steamship, the Kingston wreck near Shag Rock, then the famous Rosalie Moller and Gubal Barge.
Interspersed with the action-packed Red Sea wreck diving, we experienced a few reef dives where I was pleasantly surprised by many fish I had not seen before, like Arabian angelfish, Heber's trevally and yellowtail tang, all endemic to the Red Sea. There were many incredibly large morays. Another highlight of everyone's trip was diving with a pod of dolphins at Dolphin Reef and then again at Shadwan Island.
One way to tell if a liveaboard is popular is to see how many of your fellow guests are repeat customers, having enjoyed their 1st experience onboard so much they have come back for more. On day 1, I discovered this was the case on my Red Sea scuba diving trip and after this positive beginning, I soon found out why: Blue Planet has exceptional guest service that won't cost you the earth. The schedule ran so smoothly and pleasantly that it was easy for me to forget the downside of the boat being smaller and older than I was used to.
I was relieved to find the water temperature was 26-27°C which was easily countered by a hood and shortie under a long 3 mm wetsuit. No gloves of course as the Red Sea authorities have banned them at many dive sites in an effort to safeguard the reefs. It is always a good idea to check the water temperatures before planning which season to scuba dive in the Red Sea. We were favoured with warm, sunny days tempered with a brisk sea breeze and 20m visibility, which isn't bad going for November.
The diving was enhanced by our Tour Leader, Ashraf's briefings which displayed his thorough knowledge of the sites we would visit each day. MY Blue Planet I's 7m beam makes for a wide dive deck which is used for half the dives. We were taken to the more difficult sites to access on the Zodiac dinghy.
In a group of 14, the more experienced guests dive independently without a Divemaster. There isn't much macro diving so the lack of guidance is not missed too much. The less experienced guests are accompanied by the Divemaster, keeping in mind I'd recommend advanced certification and a minimum of 50 dives if you plan to join a Red Sea North & Wrecks Tour.
Although I personally would prefer 2 Divemasters and 2 dinghies servicing 14 guests, the yacht is not built to cater for this option. I'd also advise the addition of a sunset dive to the schedule for people who don't enjoy night diving.
The lower-deck cabins are roomy enough with en-suite bathrooms being a luxury at the price. There are no fans and the air-conditioner was not that strong. The good news is they will be transforming the 2 smaller upper deck cabins into larger, deluxe cabins in 2010.
The saloon has enough room for 16 guests, but the sundeck doesn't have many mattresses. I enjoyed a few movies, but only found 1 reef guide book and think a few diving magazines would have been fun to pass the time with between dives.
They served a large variety of Egyptian and Western dishes, including appetisers, vegetarian options, fish, soups and desserts. After the 1st dive each day guests are treated to fruit salad, toast, meat and cheese.
Conveniently departing from Hurghada's Marriot Hotel, there are many direct flights from Europe, Sharm El Sheikh and the Sinai Peninsula. I chose to fly into Luxor and was rewarded with speedy customs clearance, then had a relaxed taxi ride into Hurghada. Next time I plan my Red Sea diving, I will probably add in an antiquities tour cruise along the River Nile.
While reviewing our cruise with the other guests on the final night, MY Blue Planet I came out flying with 8 out of 10 for return on investment. This is a fair result if you put diving first and prepare yourself for a liveaboard that is not focussed on luxury.
So I set off home, still dreaming of my great experiences at Thistlegorm and deciding this is definitely a Red Sea site to scuba dive again soon.
Read the full version by Sheldon Hey: Blue Planet Red Sea Northern Wrecks Trip Report.


The following is a list of some of the web sites that ClassicSoft, LLC has done. All of these web sites run off the Web Content Framework.
Brick & Mortar store front uses the web site to promote their products and services.
Jerry's son was diagnosed with Lukemia. ClassicSoft in cooperation with Kool Software, donated this web site to help friends and family stay in contact on the internet.
K2 Custom Homes is a very successful Custom Home Builder in Arizona. The web site was built to show off their designs and work.
The Following Web Sites use ClassicSoft's Scholarship Fund ManagerTM Application Service.
Scholarship Fund ManagerTM is the software that runs a Student Tuition Organization. Everything from Tracking Donors, Applicants and Schools to Handling Payments and Integration with Quickbooks.
The Application and the Web site are tied together allowing for real-time changes to be present on the web site and in the application. The web site can handle hundreds of donations and take hundreds of applications for scholarships at the same time without the need of additional personal.
JTO is a Student Tuition Organization helping provide scholarships for students who wish to attend private school in Arizona but cannot afford it.
TOPS is a Student Tuition Organization helping provide scholarships for students who wish to attend private school in Arizona but cannot afford it.
IBE is a Student Tuition Organization helping provide scholarships for students who wish to attend private school in Arizona but cannot afford it.
ASF is a Student Tuition Organization helping provide scholarships for students who wish to attend private school in Arizona but cannot afford it.
This is the sister site for ASF that allows Corporatations to get more information and submit information for donations on-line.


The pace of change never ceases to amaze me, and some of the uses for new technologies make things interesting, to say the least! The trend over the last decade or so has been toward information sharing. Indeed, consumers now expect information to be free. This shift has changed the business model for many firms, including law firms, who now have potential clients reading the law online and finding articles, blogs, and other information (some of it incorrect!) on the Internet.
The book market is one where there are significant shifts in progress. Amazon has offered its Kindle e-book reader for several years and has many titles available for purchase. Others are now in the game, offering readers more choices. Forrester estimates that fewer than 10% of adults in the U.S. now read their book content online, but the market is growing.
Recently, Google got into the game, opening its eBookstore and offering over 3 million titles for download. Their stated goal is to scan every book ever printed and make them all available online. There is speculation that the next step will be an ad-supported book publishing model. This means that you would be able to read the book for free as long as you accept that there would be ads showing on the screen as you read. And because the book is read online, the ads would be current and relevant. Buy the book, and the ads go away.
What does this mean to you as a business owner or manager? One of the things we promote at Lawyers Marketing Agency is the use of books or white papers (Decision Making Guides) as a marketing tool. Many of our clients have gotten great results by offering a free book on personal injury, workers' compensation, or another practice area. Writing a book (or using a ghost writer) positions you as an expert, and readers appreciate the free advice—your gift to them. Many pass along the book to family and friends or hang on to it for future reference. Your book can be made available to online readers (for sale or free) or printed for those folks who do not yet read their books online.
Take it a step further: consider pay-per-click (PPC) campaigns to entice visitors with a free copy of your book or Decision Making Guide. This brings visitors to your website, improves PPC response rates and provides for a more successful campaign!
Marketing by offering free information pays dividends in the long run, providing value to the client or prospect and visibility/goodwill for the firm. To learn more about using Books or Decision Making Guides to market your firm, contact us.


text:
import type { AlgoliaSearchHelper } from 'algoliasearch-helper';
import algoliasearchHelper, {
  SearchResults,
  SearchParameters,
} from 'algoliasearch-helper';
import type { CurrentRefinementsConnectorParamsItem } from '../connectCurrentRefinements';
import connectCurrentRefinements from '../connectCurrentRefinements';
import { createSearchClient } from '@instantsearch/mocks/createSearchClient';
import {
  createDisposeOptions,
  createInitOptions,
  createRenderOptions,
} from '../../../../test/createWidget';
import { createSingleSearchResponse } from '@instantsearch/mocks/createAPIResponse';

describe('connectCurrentRefinements', () => {
  describe('Usage', () => {
    it('throws if given both `includedAttributes` and `excludedAttributes`', () => {
      const customCurrentRefinements = connectCurrentRefinements(() => {});

      expect(() => {
        customCurrentRefinements({
          includedAttributes: ['query'],
          excludedAttributes: ['brand'],
        });
      }).toThrowErrorMatchingInlineSnapshot(`
"The options \`includedAttributes\` and \`excludedAttributes\` cannot be used together.

See documentation: https://www.algolia.com/doc/api-reference/widgets/current-refinements/js/#connector"
`);
    });

    it('is a widget', () => {
      const render = jest.fn();
      const unmount = jest.fn();

      const customCurrentRefinements = connectCurrentRefinements(
        render,
        unmount
      );

      const widget = customCurrentRefinements({});

      expect(widget).toEqual(
        expect.objectContaining({
          $$type: 'ais.currentRefinements',
          init: expect.any(Function),
          render: expect.any(Function),
          dispose: expect.any(Function),
        })
      );
    });
  });

  describe('Lifecycle', () => {
    it('renders during init and render', () => {
      const helper = algoliasearchHelper(createSearchClient(), 'indexName', {});
      helper.search = jest.fn();
      // test that the dummyRendering is called with the isFirstRendering
      // flag set accordingly
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);
      const widget = customCurrentRefinements({
        includedAttributes: ['query'],
      });

      // test if widget is not rendered yet at this point
      expect(rendering).toHaveBeenCalledTimes(0);

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );

      // test that rendering has been called during init with isFirstRendering = true
      expect(rendering).toHaveBeenCalledTimes(1);
      // test if isFirstRendering is true during init
      expect(rendering.mock.calls[0][1]).toBe(true);

      const firstRenderingOptions = rendering.mock.calls[0][0];
      expect(firstRenderingOptions.items).toEqual([]);
      expect(firstRenderingOptions.refine).toBeInstanceOf(Function);
      expect(firstRenderingOptions.createURL).toBeInstanceOf(Function);
      expect(firstRenderingOptions.widgetParams).toEqual({
        includedAttributes: ['query'],
      });

      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
          createURL: () => '#',
        })
      );

      // test that rendering has been called during init with isFirstRendering = false
      expect(rendering).toHaveBeenCalledTimes(2);
      expect(rendering.mock.calls[1][1]).toBe(false);

      const secondRenderingOptions = rendering.mock.calls[0][0];

      expect(secondRenderingOptions.items).toEqual([]);
      expect(secondRenderingOptions.refine).toBeInstanceOf(Function);
      expect(secondRenderingOptions.createURL).toBeInstanceOf(Function);
      expect(secondRenderingOptions.widgetParams).toEqual({
        includedAttributes: ['query'],
      });
    });

    it('does not throw without the unmount function', () => {
      const helper = algoliasearchHelper(createSearchClient(), 'indexName', {});
      const rendering = () => {};
      const customCurrentRefinements = connectCurrentRefinements(rendering);
      const widget = customCurrentRefinements({});

      expect(() =>
        widget.dispose!(createDisposeOptions({ helper, state: helper.state }))
      ).not.toThrow();
    });

    describe('getRenderState', () => {
      test('returns the render state', () => {
        const renderFn = jest.fn();
        const unmountFn = jest.fn();
        const createCurrentRefinements = connectCurrentRefinements(
          renderFn,
          unmountFn
        );
        const configure = createCurrentRefinements({});

        const renderState = configure.getRenderState({}, createInitOptions());

        expect(renderState.currentRefinements).toEqual({
          items: [],
          canRefine: false,
          refine: expect.any(Function),
          createURL: expect.any(Function),
          widgetParams: {},
        });
      });

      test('returns the render state with scoped results', () => {
        const renderFn = jest.fn();
        const unmountFn = jest.fn();
        const createCurrentRefinements = connectCurrentRefinements(
          renderFn,
          unmountFn
        );
        const configure = createCurrentRefinements({});
        const helper = algoliasearchHelper(createSearchClient(), 'indexName', {
          index: 'indexName',
          hierarchicalFacets: [
            {
              name: 'category',
              attributes: ['category', 'subCategory'],
              separator: ' > ',
            },
          ],
        });

        configure.init!(createInitOptions());

        helper.toggleFacetRefinement('category', 'Decoration');

        const renderState = configure.getRenderState(
          {},
          createRenderOptions({
            helper,
            scopedResults: [
              {
                indexId: 'indexName',
                helper,
                results: new SearchResults(helper.state, [
                  createSingleSearchResponse({
                    hits: [],
                    facets: {
                      category: {
                        Decoration: 880,
                      },
                      subCategory: {
                        'Decoration > Candle holders & candles': 193,
                        'Decoration > Frames & pictures': 173,
                      },
                    },
                  }),
                  createSingleSearchResponse({
                    facets: {
                      category: {
                        Decoration: 880,
                        Outdoor: 47,
                      },
                    },
                  }),
                ]),
              },
            ],
          })
        );

        expect(renderState.currentRefinements).toEqual({
          items: [
            {
              attribute: 'category',
              indexName: 'indexName',
              label: 'category',
              refine: expect.any(Function),
              refinements: [
                {
                  attribute: 'category',
                  count: 880,
                  exhaustive: true,
                  label: 'Decoration',
                  type: 'hierarchical',
                  value: 'Decoration',
                },
              ],
            },
          ],
          canRefine: true,
          refine: expect.any(Function),
          createURL: expect.any(Function),
          widgetParams: {},
        });
      });
    });
  });

  describe('getWidgetRenderState', () => {
    test('returns the widget render state', () => {
      const renderFn = jest.fn();
      const unmountFn = jest.fn();
      const createCurrentRefinements = connectCurrentRefinements(
        renderFn,
        unmountFn
      );
      const configure = createCurrentRefinements({});

      const renderState = configure.getWidgetRenderState(createInitOptions());

      expect(renderState).toEqual({
        items: [],
        canRefine: false,
        refine: expect.any(Function),
        createURL: expect.any(Function),
        widgetParams: {},
      });
    });

    test('returns the widget render state with scoped results', () => {
      const renderFn = jest.fn();
      const unmountFn = jest.fn();
      const createCurrentRefinements = connectCurrentRefinements(
        renderFn,
        unmountFn
      );
      const configure = createCurrentRefinements({});
      const helper = algoliasearchHelper(createSearchClient(), 'indexName', {
        index: 'indexName',
        hierarchicalFacets: [
          {
            name: 'category',
            attributes: ['category', 'subCategory'],
            separator: ' > ',
          },
        ],
      });

      configure.init!(createInitOptions());

      helper.toggleFacetRefinement('category', 'Decoration');

      const renderState = configure.getWidgetRenderState(
        createRenderOptions({
          helper,
          scopedResults: [
            {
              indexId: 'indexName',
              helper,
              results: new SearchResults(helper.state, [
                createSingleSearchResponse({
                  hits: [],
                  facets: {
                    category: {
                      Decoration: 880,
                    },
                    subCategory: {
                      'Decoration > Candle holders & candles': 193,
                      'Decoration > Frames & pictures': 173,
                    },
                  },
                }),
                createSingleSearchResponse({
                  facets: {
                    category: {
                      Decoration: 880,
                      Outdoor: 47,
                    },
                  },
                }),
              ]),
            },
          ],
        })
      );

      expect(renderState).toEqual({
        items: [
          {
            attribute: 'category',
            indexName: 'indexName',
            label: 'category',
            refine: expect.any(Function),
            refinements: [
              {
                attribute: 'category',
                count: 880,
                exhaustive: true,
                label: 'Decoration',
                type: 'hierarchical',
                value: 'Decoration',
              },
            ],
          },
        ],
        canRefine: true,
        refine: expect.any(Function),
        createURL: expect.any(Function),
        widgetParams: {},
      });
    });

    test('resets the page on refine()', () => {
      const helper = algoliasearchHelper(createSearchClient(), 'indexName', {
        facets: ['facet1'],
      })
        .addFacetRefinement('facet1', 'facetValue1')
        .setPage(5);
      const widget = connectCurrentRefinements(jest.fn(), jest.fn())({});

      const { refine } = widget.getWidgetRenderState(
        createInitOptions({ helper })
      );

      refine({
        attribute: 'facet1',
        value: 'facetValue1',
        type: 'facet',
        label: 'facet1',
      });

      expect(helper.state.page).toBe(0);
    });
  });

  describe('Widget options', () => {
    let helper: AlgoliaSearchHelper;

    beforeEach(() => {
      helper = algoliasearchHelper(createSearchClient(), 'indexName', {
        facets: ['facet1', 'facet2', 'facet3'],
      });
      helper.search = jest.fn();
    });

    it('includes all attributes by default except the query', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({});

      helper
        .addFacetRefinement('facet1', 'facetValue1')
        .addFacetRefinement('facet2', 'facetValue2')
        .addFacetRefinement('facet3', 'facetValue3')
        .setQuery('query');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );
      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
          createURL: () => '#',
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual(
        expect.arrayContaining([
          expect.objectContaining({
            attribute: 'facet1',
          }),
          expect.objectContaining({
            attribute: 'facet2',
          }),
          expect.objectContaining({
            attribute: 'facet3',
          }),
        ])
      );
      expect(rendering.mock.calls[0][0].items).toEqual(
        expect.not.arrayContaining([
          expect.objectContaining({
            attribute: 'query',
          }),
        ])
      );
    });

    it('includes only the `includedAttributes`', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({
        includedAttributes: ['facet1', 'query'],
      });

      helper
        .addFacetRefinement('facet1', 'facetValue1')
        .addFacetRefinement('facet2', 'facetValue2')
        .setQuery('query');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );
      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual([
        expect.objectContaining({
          attribute: 'facet1',
        }),
        expect.objectContaining({
          attribute: 'query',
        }),
      ]);
    });

    it('does not include query if empty', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({
        includedAttributes: ['query'],
      });

      helper.setQuery('');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );
      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual([]);
    });

    it('does not include query if whitespaces', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({
        includedAttributes: ['query'],
      });

      helper.setQuery(' ');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );
      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual([]);
    });

    it('excludes the `excludedAttributes` (and overrides the default ["query"])', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({
        excludedAttributes: ['facet2'],
      });

      helper
        .addFacetRefinement('facet1', 'facetValue1')
        .addFacetRefinement('facet2', 'facetValue2')
        .setQuery('query');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );
      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual([
        expect.objectContaining({
          attribute: 'facet1',
        }),
        expect.objectContaining({
          attribute: 'query',
        }),
      ]);
    });

    it('transformItems is applied', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({
        transformItems: (items) =>
          items.map((item) => ({
            ...item,
            transformed: true,
          })),
      });

      helper
        .addFacetRefinement('facet1', 'facetValue1')
        .addFacetRefinement('facet2', 'facetValue2')
        .addFacetRefinement('facet3', 'facetValue3');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual(
        expect.arrayContaining([
          expect.objectContaining({
            attribute: 'facet1',
            transformed: true,
          }),
          expect.objectContaining({
            attribute: 'facet2',
            transformed: true,
          }),
          expect.objectContaining({
            attribute: 'facet3',
            transformed: true,
          }),
        ])
      );

      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual(
        expect.arrayContaining([
          expect.objectContaining({
            attribute: 'facet1',
            transformed: true,
          }),
          expect.objectContaining({
            attribute: 'facet2',
            transformed: true,
          }),
          expect.objectContaining({
            attribute: 'facet3',
            transformed: true,
          }),
        ])
      );
    });

    it('provides search results within transformItems', () => {
      const transformItems = jest.fn((items) => items);
      const customCurrentRefinements = connectCurrentRefinements(() => {});
      const widget = customCurrentRefinements({
        transformItems,
      });

      const results = new SearchResults(helper.state, [
        createSingleSearchResponse(),
      ]);

      widget.init!(createInitOptions({ helper, state: helper.state }));
      widget.render!(
        createRenderOptions({
          results,
          state: helper.state,
          helper,
        })
      );

      expect(transformItems).toHaveBeenLastCalledWith(
        expect.anything(),
        expect.objectContaining({ results })
      );
    });

    it('sort numeric refinements by numeric value', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);

      const widget = customCurrentRefinements({
        includedAttributes: ['price'],
      });

      // If sorted alphabetically, "≤ 500" is lower than "≥" so 500 should appear before 100.
      // However, we want 100 to appear before 500.
      helper
        .addNumericRefinement('price', '<=', 500)
        .addNumericRefinement('price', '>=', 100);

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );

      widget.render!(
        createRenderOptions({
          results: new SearchResults(helper.state, [
            createSingleSearchResponse(),
          ]),
          state: helper.state,
          helper,
        })
      );

      expect(rendering.mock.calls[0][0].items).toEqual([
        expect.objectContaining({
          attribute: 'price',
          refinements: [
            {
              attribute: 'price',
              label: '≥ 100',
              operator: '>=',
              type: 'numeric',
              value: 100,
            },
            {
              attribute: 'price',
              label: '≤ 500',
              operator: '<=',
              type: 'numeric',
              value: 500,
            },
          ],
        }),
      ]);
    });
  });

  describe('Rendering options', () => {
    let helper: AlgoliaSearchHelper;

    beforeEach(() => {
      helper = algoliasearchHelper(createSearchClient(), 'indexName', {
        facets: ['facet1', 'facet2', 'facet3'],
      });
      helper.search = jest.fn();
    });

    it('provides the items', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);
      const widget = customCurrentRefinements({});

      helper.addFacetRefinement('facet1', 'facetValue');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );

      const firstRenderingOptions = rendering.mock.calls[0][0];
      expect(firstRenderingOptions.items).toEqual([
        {
          indexName: 'indexName',
          attribute: 'facet1',
          label: 'facet1',
          refinements: [
            {
              attribute: 'facet1',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
      ]);

      helper
        .addFacetRefinement('facet1', 'facetValue')
        .addFacetRefinement('facet2', 'facetValue');

      widget.render!(
        createRenderOptions({
          scopedResults: [
            {
              indexId: 'firstIndex',
              helper,
              results: new SearchResults(helper.state, [
                createSingleSearchResponse({
                  index: 'firstIndex',
                }),
              ]),
            },
          ],
          state: helper.state,
          helper,
        })
      );

      const secondRenderingOptions = rendering.mock.calls[1][0];
      const items: CurrentRefinementsConnectorParamsItem[] =
        secondRenderingOptions.items;

      expect(items).toHaveLength(2);
      expect(items).toEqual([
        {
          indexName: 'indexName',
          attribute: 'facet1',
          label: 'facet1',
          refinements: [
            {
              attribute: 'facet1',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
        {
          indexName: 'indexName',
          attribute: 'facet2',
          label: 'facet2',
          refinements: [
            {
              attribute: 'facet2',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
      ]);

      expect(helper.state).toEqual(
        new SearchParameters({
          index: 'indexName',
          facets: ['facet1', 'facet2', 'facet3'],
          facetsRefinements: { facet1: ['facetValue'], facet2: ['facetValue'] },
        })
      );

      items[0].refine({
        attribute: 'facet1',
        label: 'facetValue',
        type: 'facet',
        value: 'facetValue',
      });

      expect(helper.state).toEqual(
        new SearchParameters({
          index: 'indexName',
          facets: ['facet1', 'facet2', 'facet3'],
          facetsRefinements: { facet1: [], facet2: ['facetValue'] },
        })
      );
    });

    it('provides the items from multiple scoped results', () => {
      const rendering = jest.fn();
      const customCurrentRefinements = connectCurrentRefinements(rendering);
      const widget = customCurrentRefinements({});

      helper.addFacetRefinement('facet1', 'facetValue');

      widget.init!(
        createInitOptions({
          helper,
          state: helper.state,
        })
      );

      helper
        .addFacetRefinement('facet1', 'facetValue')
        .addFacetRefinement('facet2', 'facetValue');

      widget.render!(
        createRenderOptions({
          scopedResults: [
            {
              indexId: 'firstIndex',
              helper,
              results: new SearchResults(helper.state, [
                createSingleSearchResponse({
                  index: 'firstIndex',
                }),
              ]),
            },
            {
              indexId: 'secondIndex',
              helper,
              results: new SearchResults(helper.state, [
                createSingleSearchResponse({
                  index: 'secondIndex',
                }),
              ]),
            },
          ],
          state: helper.state,
          helper,
        })
      );

      const secondRenderingOptions = rendering.mock.calls[1][0];
      const items: CurrentRefinementsConnectorParamsItem[] =
        secondRenderingOptions.items;
      expect(items).toHaveLength(4);
      expect(items).toEqual([
        {
          indexName: 'indexName',
          attribute: 'facet1',
          label: 'facet1',
          refinements: [
            {
              attribute: 'facet1',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
        {
          indexName: 'indexName',
          attribute: 'facet2',
          label: 'facet2',
          refinements: [
            {
              attribute: 'facet2',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
        {
          indexName: 'indexName',
          attribute: 'facet1',
          label: 'facet1',
          refinements: [
            {
              attribute: 'facet1',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
        {
          indexName: 'indexName',
          attribute: 'facet2',
          label: 'facet2',
          refinements: [
            {
              attribute: 'facet2',
              label: 'facetValue',
              type: 'facet',
              value: 'facetValue',
            },
          ],
          refine: expect.any(Function),
        },
      ]);
    });
  });
});

redpajama_set_name: RedPajamaGithub


text:
This article is part of a series on the History of rail transport in Great Britain.

The period from 1995 covers the history of rail transport in Great Britain following the privatisation of British Rail. During this period, passenger volumes have grown rapidly, safety has improved, and subsidies per journey have fallen. However, there is debate as to whether this is due to privatisation or to better government regulation. During this period, High Speed 1 and the West Coast Main Line upgrade were completed and more construction projects are currently under way. In this period the Coronavirus disease 2019 (COVID-19) pandemic occurred which caused a precipitous fall off in rail travel demand.

Overall rail subsidies have risen, as shown in the graph, although spend per journey has decreased. Rail subsidies have increased from £bn in 1992–93 to £bn in 2015–16 (in current prices), although subsidy per journey has fallen from £ to £. However, this masks great regional variation: for instance, in 2014–15 funding varied from "£1.41 per passenger journey in England to £6.51 per journey in Scotland and £8.34 per journey in Wales."

Due to the increase in passenger numbers and the prospect of high speed rail both within Great Britain and connecting to Europe, this period has been called the start of a new Golden Age of rail travel.  However quickly increasing passenger numbers have meant many trains (as many as 1 in 6 in some places) are very crowded at peak times. Peak-time fares have increased by over 200% (since privatisation) to deter people from travelling at these times, whereas the price of advance tickets has halved in the same period. The COVID-19 pandemic however, caused a massive drop in passenger numbers even though freight transport held up fairly well.

Government policy

Reform under the Labour government (1997–2010)

The Labour government (elected in 1997 after the majority of the privatisation process had been completed) did not completely reverse the railway privatisation of the previous administration. Initially it left the new structure largely in place, however its main innovation in the early years was the creation of the Strategic Rail Authority (SRA), initially in shadow form until the Transport Act 2000 received Royal Assent, as well as the appointment of Tom Winsor as Rail Regulator, who took a much harder line with the rail industry, and Railtrack in particular.

In the wake of the Hatfield rail crash in 2000, Railtrack entered into financial meltdown and the industry was in deep crisis. Labour refused to continue to bail out Railtrack and the company was put into Railway Administration in 2001 and a new company, Network Rail emerged to replace Railtrack in 2002. Since September 2014, Network Rail has been classified as a "government body".

The Strategic Rail Authority lasted just five years. Following the passing of the Railways Act 2005, its business was wound up and its functions transferred to the Department for Transport Rail Group and the Office for Rail Regulation. Further changes followed, which saw the government take back a greater degree of control.

Another important development occurred in the aftermath of the Potters Bar accident in May 2002 when a commuter train derailed (coincidentally on the same stretch of the East Coast Main Line as Hatfield) due to poorly maintained points. This resulted in Network Rail taking all track maintenance back in-house and the industry went on to enjoy the longest period in modern times without a fatal accident due to industry error. This came to an end in February 2007 when a Virgin Trains West Coast Class 390 Pendolino derailed near Grayrigg in Cumbria, killing one person. The cause of the accident was identical to that in Potters Bar nearly five years earlier – once again calling into question Network Rail's maintenance procedures.

In 2007, the government's preferred option was to use diesel trains running on biodiesel, its White Paper Delivering a Sustainable Railway, ruling out large-scale Railway electrification in Great Britain for the following five years.

Following Gordon Brown's appointment as Prime Minister in 2007, Andrew Adonis was appointed Transport Secretary. He immediately began work on plans for a new high-speed route between London and Birmingham (later known as High Speed 2), which would augment the West Coast Main Line. Adonis also announced plans to electrify the Great Western Main Line from London as far as Swansea, as well as infill electrification schemes in the North West of England to remove diesel traction from certain key routes. Late in 2009, the InterCity East Coast franchise collapsed for the second time in three years when incumbent operator National Express East Coast (NXEC) proved unable to meet its financial obligations. Adonis transferred the franchise to the state-owned Directly Operated Railways to operate the route under its East Coast subsidiary.

In February 2009, the Department for Transport setup a company called Diesel Trains Ltd with the intention of funding and managing the procurement of up to 200 diesel multiple unit vehicles as part of the British Government's planned purchase of as many as 1300 new rail vehicles. It was incorporated following the announcement of the first 200 vehicles in late 2008 as part of the Pre-Budget Report - the speed of this announcement (the final contract to be signed in April 2009) led the government to take the lead in financing the procurement, through a public company. However, the DfT stated that it did not intend to serve in the long-term as a lessor of rolling stock. As a consequence, the DfT planned to sell Diesel Trains Ltd once the procurement process was completed, either as a whole, or by selling its assets and contracts.

Diesel Trains Ltd was to have responsibility for the purchase and distribution of 202 DMU vehicles to three TOCs - First Great Western, First TransPennine Express and Northern Rail. The order itself was to encompass a total of 61 trains, with 19 four-car and 42 three-car.

Following the announcement in August 2009 that the Great Western Main Line was to be electrified, the order for 202 DMUs was cancelled. After lying dormant for three years, Diesel Trains Ltd was dissolved in July 2012.

Reform under the Coalition government (2010–2015)

After the 2010 General Election, the new Conservative led Coalition continued Labour's rail policies largely unaltered after a pause to review the finances. There was continuing support for the High Speed 2 scheme and further developing plans for the route, although great debate still rages over the scheme's benefits and costs. Whilst initially showing scepticism towards the electrification schemes of the Great Western route, they later gave the project its backing and work began formally in 2012. Plans were also mooted to electrify the remainder of the Midland Main Line.

In 2012, the franchising system again came under criticism after FirstGroup was awarded the InterCity West Coast franchise. Incumbent Virgin Rail Group initiated a judicial review against the decision, citing the fact that First's bid was even more ambitious than the one which had scuttled National Express East Coast less than three years earlier. Before the review took place however, newly installed Transport Secretary Patrick McLoughlin scrapped the entire bidding process for the franchise and granted Virgin an extension to its contract when "severe technical flaws" were discovered in the original bidding competition.

The Conservative government (2015–present)

The Government has moved towards allowing more competition on the intercity network through open access operators. In 2015 it approved a service run by Alliance Rail Holdings to operate between London Euston and Blackpool, and in 2016 it allowed FirstGroup to run open access services on the East Coast Main Line from October 2021 under the operating name Lumo.

Fare increases
Much debate continues over annual fare increases, although the government has now pledged to keep regulated rail fare increases at Retail Prices Index (RPI) inflation for the remainder of this Parliament. In addition much debate has continued over the financing of various rail schemes driven primarily by the huge cost and time overrun on the GWML route modernisation and electrification scheme. In connection with this, and to coincide with the Chancellor's Autumn statement in November 2015, the Bowe and Hendy reports were produced.

Rail strikes

Since April 2016, the British railway network has been severely disrupted on many occasions by wide-reaching rail strikes, affecting rail franchises across the country. The industrial action began on Southern services as a dispute over the planned introduction of driver-only operation, and has since expanded to cover many different issues affecting the rail industry; as of February 2018, the majority of the industrial action remains unresolved, with further strikes planned. The scale, impact and bitterness of the nationwide rail strikes have been compared to the 1984–85 miners' strike by the media.

Infrastructure projects
In March 2016, the National Infrastructure Commission said that Crossrail 2 should be taken forward "as a priority" and recommended that a bill should pass through Parliament by 2019 and the line should be open by 2033. Crossrail 2 is a north–south railway through London, similar to the east–west railway Crossrail which is currently under construction.

In July 2017, Chris Grayling, the secretary of state for transport announced a number of electrification schemes were to be suspended indefinitely citing the disruptive nature of electrification works and the availability of bi-mode technology. The schemes included aspects of the GWML including Cardiff to Swansea, the Midland Main Line from Kettering to Sheffield via Derby and Nottingham and Oxenholme to Windermere in the Lake District.

In February 2018, the five-year plan was published by Network Rail with significant investment though much of this was for renewals and smaller projects rather than major projects. In March 2019 the Railway Industry Association published a paper entitled Electrification Cost Challenge.

In July 2019, the Urban Transport Group released a report that showed regional rail travel had experienced a 29% growth in the ten years to 2017/18.

On 24 July 2019, Grant Shapps was appointed Secretary of State for Transport under the new Prime Minister Boris Johnson.

The Transport Select Committee have met on a number of occasions since early 2020 and considered the 'Trains Fit for the Future" ongoing enquiry which was started under the previous session under Lilian Greenwood's chairship. The report, published in March 2021, recommended a rolling programme of electrification and for the DfT to quickly publish a list of "no regret" electrification schemes. It was stated that Network Rail had already supplied a list to the DfT.

The TDNS (Traction Decarbonisation Network Strategy) Interim Business case was published in September 2020. The main theme was electrification of 13,000 single track kilometres of UK railways.

In September 2020, the Government permanently got rid of the rail franchising system. On 20 May 2021, the Government announced and published a white paper that detailed how it would transform the operation of the railways. The rail network will be partly renationalised, with infrastructure and operations brought together under a new company Great British Railways. Operations will be managed on a concessions model. According to the BBC, this represents the largest shake-up in the UK's railways since privatisation.

On 18 November 2021, the Integrated Rail Plan (IRP) was published. This affected parts of the HS2 programme including curtailing much of the eastern leg but did include full Midland Main Line electrification and upgrades. Also included was a commitment to the Transpennine north railway upgrade to include full electrification.

On the back of the IRP, the Union Connectivity Review was also published in November 2021. The Union Connectivity Review was announced on 30 June 2020 by the Prime Minister Boris Johnson. It was stated that Sir Peter Hendy would chair the review. The terms of reference were published 3 October 2020. An interim report was published March 2021.

The final report was published on 25 November 2021. In December 2021 The Telegraph newspaper reported in an apparent leak that the treasury had decided not to provide fund further electrification and thus help to decarbonise the railways.

The official announcement and confirmation that the Midland Main Line between Kettering and Market Harborough was being electrified and spades would be in the ground starting 24 December 2021 was made on 21 December 2021.

COVID-19 pandemic effect on railways in Great Britain

The COVID-19 pandemic in the United Kingdom occurred in this period and caused a catastrophic fall off in the number of passengers using the rail network although freight held up reasonably well. While passenger numbers had recovered to over 80% of their pre-Covid levels by July-September 2022, how this will affect the long-term health of the rail industry remains to be seen. Despite the pandemic the Traction Decarbonisation Strategy Interim Business case was published in July 2020. In addition, Network Rail also published its Environmental sustainability strategy.

In direct response to falling passenger numbers and revenues, the Wales & Borders operator Transport for Wales Rail was put into public ownership by the Welsh Government on 7 February 2021.

Infrastructure projects

Completed projects
The British railway system continues to be developed. Contemporary projects include:
 The West Coast Main Line upgrade (West Coast Main Line route modernisation) was a long-term project covering a series of technical aspects. Improvements included the four-tracking (from three) of the Trent Valley (a bypass of the West Midlands), redesigning the layout of several junction/stations e.g. Rugby and other associated work to increase line speed. This culminated in tilting trains at 125 mph being extended to Glasgow in 2005. The cost overruns of the programme are infamous - attributed to the wide scope of the programme (the promise to Virgin to build a 140 mph railway which would require moving block signalling) and poor project management by the defunct Railtrack.

England
 High Speed 1, a project to construct a  high-speed rail line from London to the British end of the Channel Tunnel, and involving a great deal of complex civil engineering including a  bridge over the River Medway, a  tunnel under the Thames near Dartford, a 2-mile tunnel through the North Downs,  twin tunnels running into central London, a major new railway station extension to London St Pancras, and a complex redesign and rebuild of the King's Cross St Pancras tube station. The southern phase 1 of the project opened in September 2003, and northern phase 2 opened in November 2007.
 The electrification of both the Liverpool to Manchester line and Liverpool to Wigan lines were completed in 2015 and electric Class 319 trains (on the Liverpool to Manchester Airport service) and Class 350s (on the Manchester Airport to Scotland services) have replaced diesel units. The lines between Preston and Blackpool North and also Preston - Manchester have been electrified with completion in 2018.
 Electrification of the Cross-City Line to Bromsgrove has been completed, which allowed electric trains to run from summer 2018.
 Trains from the north east to Manchester Airport now use a new section of railway, the £85 million Ordsall Chord, between Manchester Victoria and Manchester Oxford Road to access Manchester Piccadilly and continue to the airport without the need to reverse at Piccadilly and without conflicting movements at the station throat. This has been completed.

Scotland
 The Stirling-Alloa-Kincardine railway, a  extension to the network, to the north of the Firth of Forth in Scotland. A Bill for the railway was passed by the Scottish Parliament and received Royal Assent in August 2004. Work commenced in September 2005, with services running by early 2008. The line re-establishes a railway decommissioned in 1983; the new line provided passenger connections to Glasgow, and freight links between the site of Kincardine power station, now used as a loading point for coal from open-cast sites, to avoid heavy traffic through Kincardine, and Longannet power station, and the coal terminals at Hunterston Deep Water Port. Longannet power station closed in 2016. The passenger part of the scheme, from Stirling to Alloa was in any case secure, and the Scottish Parliament appear to be in favour of passenger services being extended to Rosyth. This could possibly result in passenger stations serving the communities of Clackmannan, Kincardine, and Culross or Valleyfield, and through trains once more from Stirling to Dunfermline.
 A short extension of the Glasgow-Hamilton-Motherwell, which once again links Larkhall to the railway network after 40 years. Larkhall has for some time been the largest town in Scotland without a railway station. The new £35million line follows an existing formation, and services to Larkhall railway station resumed on 12 December 2005. The new section of route is electrified and is served with trains from Dalmuir, via Glasgow Central Low Level, with connections from other northern suburbs of Glasgow such as Milngavie.
 The Airdrie-Bathgate Rail Link was completed in December 2010. The Airdrie-Bathgate project was quite extensive insofar as it included double track electrification, the present remnant of the line from just outside Edinburgh to Bathgate having been largely singled some time ago.
 The Glasgow Airport Rail Link was given the go-ahead by the Scottish Parliament in December 2006 but the project was scrapped by the new SNP minority government in September 2009. A new  spur was to be built onto the existing Inverclyde route. An element of the project that did go ahead was upgrading the Glasgow Central - Paisley line to triple track to increase capacity on the Ayrshire and Inverclyde routes. This work was completed in 2012.
 A  section of the Waverley Route from Edinburgh to Tweedbank in the Scottish Borders has been rebuilt after approval by the Scottish Parliament, which reopened on 6 September 2015. This project, also known as the Borders Railway, restored rail services to communities which have lacked access to the National Rail network since the Beeching cuts.
 The Edinburgh to Glasgow Improvement Programme or "EGIP" was an initiative started by the Scottish Government to upgrade the main railway line between Edinburgh and Glasgow via Falkirk High. The route via Shotts was then to follow. It was expected to cost around £650 million. In May 2017, a further delay was announced due to a safety critical component on the via Falkirk High route needing to be replaced.
 The line between Glasgow Queen Street railway station and Edinburgh Waverley railway station via Falkirk High railway station was electrified and electric trains started running in December 2017.
 The rolling programme of electrification in Scotland saw lines from Edinburgh and Glasgow electrified to Stirling, Dunblane and Alloa.
 The Edinburgh to Glasgow Central line via Shotts was completed on time and on budget.

Wales
 The Welsh Assembly Government re-opened the Vale of Glamorgan Line between Barry and Bridgend in 2005 and the Ebbw Valley Railway between Ebbw Vale Parkway and Cardiff Central in 2008. An extension of the line to Ebbw Vale Town opened in 2015.

Current developments
High Speed 2 (HS2) is a planned high-speed railway which will initially link the cities of London and Birmingham, followed by further extension to North West England and Yorkshire. Construction of the first phase of HS2 began in 2017 with a planned opening date of 2026, while completion of the entire network is expected in 2033. Phase One of HS2 will run between London Euston and the proposed new Birmingham Curzon Street station. Phase two will create two branches: a western leg to Manchester Piccadilly, and an eastern leg to the proposed Leeds New Lane station via the East Midlands Hub (serving Derby, Nottingham and Leicester) and Meadowhall Interchange (serving Sheffield). Phase 2A from Lichfield to Crewe received Royal Assent on 11 February 2021.
 The Thameslink Programme started in 2009 and is expected to be completed in December 2019. The project includes the lengthening of platforms, station remodelling, new railway infrastructure (e.g. viaducts) and additional rolling stock, which will allow Govia Thameslink Railway to expand their Thameslink services further north and south.
The Northern Hub is a rail project across Northern England aimed at stimulating economic growth by increasing train services, reducing journey times and electrifying lines between the major cities and towns in the north. The project was announced as the Manchester Hub, entailing a series of upgrades to cut journey times between cities in Northern England by alleviating rail bottlenecks around Manchester. Central to the project is the resolution of rail bottlenecks around Manchester city centre allowing more capacity and faster journey times between the northern cities. The construction of two through platforms at Piccadilly will allow an increase to 14 trains per hour from 10. Manchester Victoria station is being modernised to become the east–west rail interchange in northern England. Services from Liverpool to Leeds and beyond will be diverted from the Cheshire Lines route via Warrington Central and Manchester Piccadilly to the electrified line via Newton-le-Willows and Manchester Victoria.
On the Great Western Main Line, Network Rail plans to spend £5 billion on modernising the GWML and its South Wales branch plus other associated lines like the North Cotswolds which was completed in 2011. The modernisation plans were announced at separate times but their development time-scales overlap each other to represent a comprehensive modernisation plan for the Great Western and its associated lines during the second decade of the 21st century. The modernisation includes: electrification, resignalling, new rolling stock and station upgrades. According to Network Rail, the modernisation started in June 2010 and will end in 2017. On 8 November 2016 the government announced that several elements of the Great Western Main Line electrification programme would be indefinitely deferred due to cost overruns and delays. This was confirmed by Chris Grayling in July 2017 stating specifically Cardiff -Swansea electrification was cancelled and bi-mode availability made this possible without disruptive electrification works.
Crossrail is a  railway line under construction in London and its environs. It is expected to begin full operation in 2021 with a new east–west route across Greater London. Work began in 2009 on the central section of the line—a new tunnel through central London—and connections to existing lines that will become part of Crossrail. Crossrail's aim is to provide a high-frequency commuter/suburban passenger service that will link parts of Berkshire and Buckinghamshire, via central London, to Essex and South East London.
 Scotland
 Scotland has committed to a rolling programme of electrification to decarbonise the network by 2045 but with an even more aggressive target for decarbonisation of the passenger network by 2035. The first announced project is the electrification of the route to Barrhead and East Kilbride. As well as electrification, double tracking from Busby to East Kilbride is planned as well as lengthening  platforms at existing stations. Part of the project scope includes relocating Hairmyres station and a complete rebuild of East Kilbride station.
 Scotland has also published a plan and split it into components identified as: in delivery, in development or under active consideration. As of 2021 projects in delivery include improvements to Aberdeen Station and other renewals in the Carstairs area and also Motherwell. The electrification to East Kilbride is also included in this category. The branch line to Levenmouth is being reopened but the electrification work is to enable Battery electric multiple unit operation rather than full electrification. In 2021 projects considered in development are mainly those that support the decarbonisation agenda. New electrification will require new 25kV Grid Feeders and upgrading existing ones to handle the increased electrical load.  Partial electrification of the Borders Railway are included here along with Barrhead and Haymarket to Dalmeny and Leven. Projects classed as under active consideration again are almost exclusively those supporting the decarbonisation agenda and include most if not all future phases of decarbonisation plan. All of Scotland's seven cities are included and thus include improvements and electrification the routes out of Aberdeen including to the Central Belt and Inverness. The Highland Main Line from Perth to Inverness is also included in the plan. This obviously requires continuation of the previous scheme from Stirling to Dunblane and Alloa. So Dunblane to Hilton junction and Perth along with all the other necessary infrastructure improvements such as route clearance are part of the infrastructure upgrade plan. The Fife Circle line and extensions to Longannet and Dundee and Perth are all part of this. Electrification in Ayrshire and south west of Glasgow are under active consideration too.
 Wales
 The Welsh Assembly Government proposes to extend the Ebbw Valley line between Ebbw Vale and Cardiff into Newport in the future. The Assembly Government is also looking into opening the Hirwaun to Aberdare route in the Cynon Valley. In addition to further progress on the South Wales Metro, and North Wales Metro.

Timeline of improvements

2015
May: The Todmorden Curve reopened, allowing direct trains to operate between Manchester and east Lancashire. The Curve had been closed in 1965 with the tracks lifted in 1972.
December: Apperley Bridge station reopened, after being closed in 1965. It is the first of two stations between Leeds and Shipley in West Yorkshire to be reopened.

2016

 February: The first of 27 Class 387/2 Electrostar units were introduced on the Gatwick Express route between London Victoria and Gatwick Airport, replacing the Class 442s.
 March: The Norton Bridge flyover on the West Coast Main Line was brought into use.
 June:  The first of 115 Class 700 Desiro City units entered service on Thameslink.
 June: Kirkstall Forge station opened.
 July: The new Bromsgrove station opened.
 December: The westernmost segment of the western section of East West Rail opened, extending the line from Oxford Parkway to Oxford, and thus establishing a new Oxford-Marylebone service via .

2017
 April: Ilkeston station in Derbyshire, served by trains between Nottingham and Leeds, opened and Low Moor station on the Caldervale line between Bradford and Halifax reopened after being closed in 1965.
 April: Redoubling of track from Rossett to Chester on the Shrewsbury to Chester Line was completed.
 May: Cambridge North station opened.
 May: Electric 387 trains started running between London Paddington and Maidenhead following completion of electrification work.
 June: The first of 66 Class 345 Aventra units entered service on Crossrail. These replaced the 44 TfL Rail Class 315 units that previously operated this service.
 August: The first of 30 Class 707 Desiro City units entered service with South West Trains.
 October: The first Class 800 Intercity Express trains were introduced on the Great Western Main Line.
 December: The Ordsall Chord opened to passenger traffic.
 December: As part of the Edinburgh to Glasgow Improvement Programme, the first electric trains ran from Edinburgh to Glasgow via Falkirk High.

2018

 January: The line from Preston to Blackpool South including Kirkham and Wesham reopened on time with completely new signaling.
 January: Electric trains started running between Paddington and Didcot following completion of electrification work on this section of the Great Western Main Line.
 January: Infrastructure work on the Thameslink project allows 20 trains per hour between Blackfriars and St Pancras.
 January: The first passenger train ran on the completed Bermondsey dive-under.
 April: Kenilworth station opened on the line between Leamington Spa and Coventry.
 May: The first electric trains ran between Preston and Blackpool North.
 May: Services between Paddington and Heathrow Terminal 4 as well as Heathrow Central and Heathrow Terminal 4 transferred from Heathrow Express to Crossrail.
 May: Resignalling on the Halton Curve that allows trains to travel in both directions (previously trains could only travel on the line in a northbound direction) from Chester to Liverpool Lime Street (via Runcorn) was completed, allowing trains to run from May 2019.
 May: Electrification of the Cross-City Line to Bromsgrove was completed, allowing electric trains to run in July 2018.
 June: Maghull North station opened on Merseyrail's Northern line.
 July: Class 385 electric trains started running on the Edinburgh to Glasgow route.
 August: Class 802 trains entered service with Great Western Railway on certain GWR routes, mainly from London Paddington via Newbury/Exeter St. David's to Plymouth/Penzance.
 August: Mark 5A coaches hauled by Class 68 locomotives began testing on the mainline prior to their introduction with TransPennine Express.
 September: Great Northern started introducing Class 717 trains on services to and from Moorgate.
 December: Electric trains started running on the Stirling-Dunblane-Alloa line.
 December: Four-tracking of the Great Western Main Line at Filton Bank between Dr Days Junction and Filton Abbey Wood was completed.
 December: Manchester to Preston electrification was completed and Virgin Pendolino test trains ran.

2019
 April: Electrification of the Shotts Line between Edinburgh and Glasgow was completed, allowing electric trains to run from May.
 April: Vivarail Class 230 units started operating on the Marston Vale line for West Midlands Railway.
 April: Mark 5 coaches entered service on the Caledonian Sleeper.
 May: Electric trains started running on the Chase Line to Walsall.
 May: Class 710 Aventra units entered service for London Overground on the Lea Valley Lines, Gospel Oak to Barking Line, Watford DC Line and the Romford to Upminster Line.
 May: The first Class 800 Super Express trains were introduced on the East Coast Main Line.
 June: Refurbished Class 442 units entered service with South Western Railway on London Waterloo to Portsmouth/Southampton services.
 July: The first Class 195 Civity and Class 331 Civity units started running services on Arriva Rail North's network.
 July: Greater Anglia started their complete fleet replacement by introducing their first Class 755 units.
 September: Class 801 units made their debut for London North Eastern Railway on London to Leeds services.
 November: The first of twelve 5-car Class 397 Civity trains entered service for TransPennine Express.
 December: Services between Paddington and Reading transferred from Great Western Railway to Crossrail.
December: Robroyston and Warrington West stations open with the December timetable change.
 December: All of the Pacer (Class 142, Class 143 and Class 144) units were to be withdrawn from service by the end of December 2019 unless they receive modifications to comply with the Disability Discrimination Act of 2005. However, it has been confirmed that some will remain in service past the December 2019 deadline.
 December: The Thameslink Programme is scheduled for completion, allowing for 24 trains per hour between Blackfriars and St Pancras.
 December: Class 387s specially converted for use on the route will enter service for Heathrow Express.

2020
 January: The first Class 745 trains began operating for Greater Anglia.
 January: The first electric trains ran on the Great Western Main Line to Cardiff.
 February: Worcestershire Parkway railway station opened.
 November: Greater Anglia introduced the Class 720 into service.

2021
 January: Electrification of the Midland Main Line to Corby is completed.
May: Class 769 bi-mode units converted from electric Class 319 trains were introduced into service with Northern.
May: The final Pacer unit (a Class 143) ran its final service for Transport for Wales.
October: Open access operator Lumo started running services on the ECML.
 December: Kettering to Market Harborough electrification officially announced and starts.
 December: Work starts on Bolton (Lostock) to Wigan upgrade and electrification.
December: Soham railway station reopened.

2022
 May: The central section of Crossrail (Paddington to Abbey Wood) opened.
 July: Barking Riverside station opened on the Gospel Oak to Barking line
 October: West Midlands Trains started introducing their new fleet of Class 196 trains.
 November: CAF Class 197 Civity DMUs began entering service with Transport for Wales Rail.

2023
 January: Class 231 Flirt trains began operating with Transport for Wales Rail.
 January: Merseyrail started introducing the first of 52 new four-car Class 777 trains to replace their three-car Class 507 and Class 508 trains.
 South Western Railway start introducing their new Class 701 trains.
 c2c start introducing their new fleet of six 10-car Bombardier Class 720 trains.
 Stadler Class 398 Citylink tram-trains and Class 756 Flirt trains are due to begin operating with Transport for Wales Rail.
 Brent Cross West station is due to open on the Thameslink route in North London.
 Avanti West Coast will begin introducing their new fleet of Class 805 & Class 807 units.
 Class 810 units will come into service for East Midlands Railway.
 New stations are planned to open at Willenhall and Darlaston
 West Midlands Trains introduce the first Class 730 trains

2024
 Services due to start running on the western section of the East West Rail from Oxford to Bletchley.
 ETCS signalling will be installed on the ECML between London and Peterborough.
 Bolton (Lostock) to Wigan electrification scheduled for completion.

Present locomotives and rolling stock

Diesel locomotives

* BR Class 73 is an electro-diesel locomotive which allows electrified and non electrified route workings.

Electric locomotives

a BR Class 73 and 88 are electro-diesel locomotives which allow both electrified and non electrified route workings.

Diesel multiple units

AC electric multiple units

Dual AC/DC electric multiple units

DC electric multiple units

Bi-mode diesel/electric multiple units

Coaches

 Details of withdrawn locomotives and rolling stock: See article Withdrawn British Rail stock

See also
Campaign to Bring Back British Rail
Campaign to Electrify Britain's Railways
Financing of the rail industry in Great Britain
History of rail transport in Great Britain 1948–1994
Transport for the North
UK Ultraspeed
West Coast Main Line route modernisation

References

Further reading

1995
Railway lines

redpajama_set_name: RedPajamaWikipedia


text:
Written on March 13th, 2016
The Dangerous Audrey II
I have an aloe vera plant that I call Audrey. It just keeps growing and growing. I give away offshoots all the time. I tear off limbs and throw them away. And it still grows. But by comparison to Audrey II, now on stage at the St. Jacobs Country Playhouse, my plant is small stuff. Nevertheless, I'm going to keep watching for big red lips to appear.
Little Shop of Horrors is indeed a horror musical about a plant with a big mouth that feeds on human blood and bodies. You need to know that before you go. A pair of patrons sitting behind us were caught off guard and found it quite disgusting when the plant started devouring human limbs. They left at intermission. What they failed to appreciate was the crazy comedy that redeems the gory tale. Director Mike Jackson deserves credit for putting this hilarious horror show together, with a cast that capitalizes on the over-the-top comedy and offers excellent singing. As well, there is a very imaginative set.
The hapless nerd, Seymour, works in Mr. Mushnik's flower shop, along with the blonde, not-to-bright, Audrey. Seymour has a big crush on Audrey, so when he develops a new plant species, he names it Audrey II, and lovingly refers to it as Twoie. Something akin to a Venus Fly Trap, Audrey II craves blood and soon there are Band-Aids on all Seymour's fingers. The plant grows and demands more. Audrey has a cruel boyfriend who bullies and beats her. He's a nasty, mad, dentist, so Seymour can justify feeding him to Audrey II. And on it goes…
Ken James Stewart is perfect as the despondent Seymour, who finally finds love, only to have it taken from him. Jayme Armstrong is the quintessential dumb chick as Audrey, who comments that others wear "cheap and tasteless outfits", while standing there in a too short, too tight leopard print dress. Stewart and Armstrong's choreography with four red telephone cords in the top of act two is marvellous.
Nicholas Rice's curmudgeonly Mr. Mushnik is comical, and the trio of neighbourhood singers on Skid Row – Crystal, Chiffon, and Ronnette (Divine Brown, Vanessa Cobham, and Shahi Teruko) – act as narrators.
Stealing the show is Jamie McKnight: He is blessed with a perfect sense of comedic timing and an amazing singing voice. McKnight is hilarious as the threatening and sadistic dentist Orin Scrivello. But lest you think he is devoured by Audrey II, never to be seen again, don't worry. McKnight keeps popping up throughout the second act. A quick change artist, he handles a variety of comedic parts, including an old lady reminiscent of Enid on TV's 22 Minutes. McKnight has perfected the art of the dead pan face.
Two more characters are only on stage for brief moments, but perform hugely important roles. Lee Siegel, in addition to portraying a Skid Row bum, is the amazing voice of Audrey II. Siegel belts her demands flawlessly with his powerful voice. Gregory Pember is seen on stage occasionally, and also handles the role of puppeteer, bringing Audrey II to life. When Pember takes his bow at the end of the show, it is amazing to see the harness and equipment he needs to wear to operate the man-eating plant.
The set is outstanding. The stage rotates to show the shop exterior on Skid Row, then turns back to show the shop interior. It also quickly converts to the horrific dentist's office. Props are excellent, especially the rapidly growing plant that expands in each scene.
This is the only opportunity this year to see Little Shop of Horrors, which closes in St. Jacobs March 26. But I'm guessing with this quality cast and set, we will see it in other Drayton venues next year. Let's hope so.
Little Shop of Horrors continues with eight shows a week until March 26 at St. Jacobs Country Playhouse. Tickets are available by calling the Box Office Toll Free 1-855-372-9866, or check http://www.draytonentertainment.com/
Photo: Jayme Armstrong as Audrey, Ken James Stewart as Seymour, with the trio in the background. Photo by Hilary Gauld Camilleri.
Book and Lyrics by Howard Ashman
Music by Alan Menken
Directed & Choreographed by Mike Jackson
Musical Direction by Michael Barber
Performed by Jayme Armstrong, Divine Brown, Vanessa Cobham, Jamie McKnight, Gregory Pember, Nicholas Rice, Lee Siegel, Ken James Stewart, Shahi Teruko
St. Jacobs Country Playhouse, St. Jacobs
March 8 to 26, 2016

redpajama_set_name: RedPajamaCommonCrawl