text:
package com.sequenceiq.cloudbreak.service.multiaz;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.util.CollectionUtils;

import com.sequenceiq.cloudbreak.api.endpoint.v4.stacks.base.InstanceStatus;
import com.sequenceiq.cloudbreak.cloud.model.CloudSubnet;
import com.sequenceiq.cloudbreak.common.exception.CloudbreakServiceException;
import com.sequenceiq.cloudbreak.common.json.Json;
import com.sequenceiq.cloudbreak.common.mappable.CloudPlatform;
import com.sequenceiq.cloudbreak.common.network.NetworkConstants;
import com.sequenceiq.cloudbreak.controller.validation.network.MultiAzValidator;
import com.sequenceiq.cloudbreak.core.flow2.dto.NetworkScaleDetails;
import com.sequenceiq.cloudbreak.domain.stack.instance.InstanceGroup;
import com.sequenceiq.cloudbreak.domain.stack.instance.InstanceMetaData;
import com.sequenceiq.cloudbreak.domain.stack.instance.network.InstanceGroupNetwork;
import com.sequenceiq.cloudbreak.dto.InstanceGroupDto;
import com.sequenceiq.cloudbreak.view.InstanceGroupView;
import com.sequenceiq.environment.api.v1.environment.model.response.DetailedEnvironmentResponse;
import com.sequenceiq.environment.api.v1.environment.model.response.EnvironmentNetworkResponse;

@ExtendWith(MockitoExtension.class)
public class MultiAzCalculatorServiceTest {

    private static final String SUBNET_ID = "SUBNET_ID";

    private static final String AVAILABILITY_ZONE = "AVAILABILITY_ZONE";

    private static final int SINGLE_INSTANCE = 1;

    private static final int NO_SUBNETS = 0;

    private static final int SINGLE_SUBNET = 1;

    @Mock
    private MultiAzValidator multiAzValidator;

    @InjectMocks
    private MultiAzCalculatorService underTest;

    @Test
    public void testPrepareSubnetAzMap() {
        DetailedEnvironmentResponse detailedEnvironmentResponse = new DetailedEnvironmentResponse();
        EnvironmentNetworkResponse environmentNetworkResponse = new EnvironmentNetworkResponse();
        environmentNetworkResponse.setSubnetMetas(Map.of(
                cloudSubnetName(1), cloudSubnet(1),
                cloudSubnetName(2), cloudSubnet(2)
        ));
        detailedEnvironmentResponse.setNetwork(environmentNetworkResponse);

        Map<String, String> result = underTest.prepareSubnetAzMap(detailedEnvironmentResponse);

        Assertions.assertEquals(result.size(), 4);
        Assertions.assertEquals(result.get(cloudSubnetName(1)), cloudSubnetAz(1));
        Assertions.assertEquals(result.get(cloudSubnetName(2)), cloudSubnetAz(2));
    }

    @Test
    public void testPrepareMultiAzMapWhenAvailabilityZoneNotNull() {
        DetailedEnvironmentResponse detailedEnvironmentResponse = new DetailedEnvironmentResponse();
        EnvironmentNetworkResponse environmentNetworkResponse = new EnvironmentNetworkResponse();
        environmentNetworkResponse.setSubnetMetas(Map.of(
                cloudSubnetName(1), cloudSubnet(1),
                cloudSubnetName(2), cloudSubnet(2)
        ));
        detailedEnvironmentResponse.setNetwork(environmentNetworkResponse);

        Map<String, String> actual = underTest.prepareSubnetAzMap(detailedEnvironmentResponse, "az-1");
        Assertions.assertEquals(2, actual.size());
        Assertions.assertEquals("az-1", actual.get("name-1"));
        Assertions.assertEquals("az-1", actual.get("1"));
    }

    static Object[][] prepareSubnetAzMapTestWhenEmptyResultDataProvider() {
        return new Object[][]{
                // testCaseName environment
                {"environment=null", null},
                {"network=null", DetailedEnvironmentResponse.builder().withNetwork(null).build()},
                {"subnetMetas=null",
                        DetailedEnvironmentResponse.builder().withNetwork(EnvironmentNetworkResponse.builder().withSubnetMetas(null).build()).build()},
        };
    }

    @ParameterizedTest(name = "{0}")
    @MethodSource("prepareSubnetAzMapTestWhenEmptyResultDataProvider")
    void prepareSubnetAzMapTestWhenEmptyResult(String testCaseName, DetailedEnvironmentResponse environment) {
        Map<String, String> result = underTest.prepareSubnetAzMap(environment);

        assertThat(result).isNotNull();
        assertThat(result).isEmpty();
    }

    static Object[][] testSubnetDistributionForWholeInstanceGroupData() {
        return new Object[][]{
                // cloudPlatform, subnetCount, instanceCount, expectedCounts, supported
                {CloudPlatform.AWS, 1, 99, Arrays.asList(99L), true},
                {CloudPlatform.AWS, 3, 99, Arrays.asList(33L, 33L, 33L), true},
                {CloudPlatform.AWS, 3, 60, Arrays.asList(20L, 20L, 20L), true},
                {CloudPlatform.AWS, 3, 59, Arrays.asList(20L, 20L, 19L), true},
                {CloudPlatform.AWS, 3, 58, Arrays.asList(20L, 19L, 19L), true},
                {CloudPlatform.AWS, 3, 57, Arrays.asList(19L, 19L, 19L), true},
                {CloudPlatform.AWS, 3, 56, Arrays.asList(19L, 19L, 18L), true},
                {CloudPlatform.AWS, 4, 60, Arrays.asList(15L, 15L, 15L, 15L), true},
                {CloudPlatform.AWS, 4, 59, Arrays.asList(15L, 15L, 15L, 14L), true},
                {CloudPlatform.AWS, 4, 58, Arrays.asList(15L, 15L, 14L, 14L), true},
                {CloudPlatform.AWS, 4, 57, Arrays.asList(15L, 14L, 14L, 14L), true},
                {CloudPlatform.AWS, 4, 56, Arrays.asList(14L, 14L, 14L, 14L), true},
                {CloudPlatform.YARN, 0, 0, Arrays.asList(), false},
        };
    }

    @ParameterizedTest(name = "testSubnetDistributionForWholeInstanceGroup " +
            "with {0} platform when {1} subnets and {2} instances should result in {3} subnet counts")
    @MethodSource("testSubnetDistributionForWholeInstanceGroupData")
    public void testSubnetDistributionForWholeInstanceGroup(CloudPlatform cloudPlatform, int subnetCount, int instanceCount, List<Long> expectedCounts,
            boolean supported) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }
        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                (InstanceGroup) instanceGroup.getInstanceGroup());

        List<Long> actualCounts = new ArrayList<>();
        for (int i = 0; i < subnetCount; i++) {
            int finalI = i;
            actualCounts.add(instanceGroup.getInstanceMetadataViews()
                    .stream()
                    .filter(instance -> instance.getSubnetId().equals(cloudSubnetName(finalI)))
                    .count());
        }
        Collections.sort(expectedCounts);
        Collections.sort(actualCounts);

        Assertions.assertEquals(expectedCounts, actualCounts);
    }

    @ParameterizedTest(name = "testSubnetDistributionForWholeInstanceGroupWhenPrepopulatedForeignSubnetId " +
            "with {0} platform when {1} subnets and {2} instances should result in {3} subnet counts")
    @MethodSource("testSubnetDistributionForWholeInstanceGroupData")
    public void testSubnetDistributionForWholeInstanceGroupWhenPrepopulatedForeignSubnetId(CloudPlatform cloudPlatform, int subnetCount, int instanceCount,
            List<Long> expectedCounts, boolean supported) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        InstanceMetaData instanceWithPrepopulatedForeignSubnetId = instanceMetaData(instanceCount, SUBNET_ID, AVAILABILITY_ZONE, InstanceStatus.REQUESTED);
        instanceGroup.getInstanceMetadataViews().add(instanceWithPrepopulatedForeignSubnetId);

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                (InstanceGroup) instanceGroup.getInstanceGroup());

        List<Long> actualCounts = new ArrayList<>();
        for (int i = 0; i < subnetCount; i++) {
            int finalI = i;
            actualCounts.add(instanceGroup.getInstanceMetadataViews()
                    .stream()
                    .filter(instance -> instance.getSubnetId().equals(cloudSubnetName(finalI)))
                    .count());
        }
        Collections.sort(expectedCounts);
        Collections.sort(actualCounts);

        Assertions.assertEquals(expectedCounts, actualCounts);

        assertThat(instanceWithPrepopulatedForeignSubnetId.getSubnetId()).isEqualTo(SUBNET_ID);
        assertThat(instanceWithPrepopulatedForeignSubnetId.getAvailabilityZone()).isEqualTo(AVAILABILITY_ZONE);
    }

    static Object[][] testSubnetDistributionForWholeInstanceGroupWhen5InstancesWithPrepopulatedKnownSubnetIdData() {
        return new Object[][]{
                // cloudPlatform, subnetCount, instanceCount, expectedCounts, supported
                {CloudPlatform.AWS, 1, 99, Arrays.asList(104L), true},
                {CloudPlatform.AWS, 3, 99, Arrays.asList(35L, 35L, 34L), true},
                {CloudPlatform.AWS, 3, 60, Arrays.asList(22L, 22L, 21L), true},
                {CloudPlatform.AWS, 3, 59, Arrays.asList(22L, 21L, 21L), true},
                {CloudPlatform.AWS, 3, 58, Arrays.asList(21L, 21L, 21L), true},
                {CloudPlatform.AWS, 3, 57, Arrays.asList(21L, 21L, 20L), true},
                {CloudPlatform.AWS, 3, 56, Arrays.asList(21L, 20L, 20L), true},
                {CloudPlatform.AWS, 4, 60, Arrays.asList(17L, 16L, 16L, 16L), true},
                {CloudPlatform.AWS, 4, 59, Arrays.asList(16L, 16L, 16L, 16L), true},
                {CloudPlatform.AWS, 4, 58, Arrays.asList(16L, 16L, 16L, 15L), true},
                {CloudPlatform.AWS, 4, 57, Arrays.asList(16L, 16L, 15L, 15L), true},
                {CloudPlatform.AWS, 4, 56, Arrays.asList(16L, 15L, 15L, 15L), true},
                {CloudPlatform.YARN, 0, 0, Arrays.asList(), false},
        };
    }

    @ParameterizedTest(name = "testSubnetDistributionForWholeInstanceGroupWhen5InstancesWithPrepopulatedKnownSubnetId " +
            "with {0} platform when {1} subnets and {2} instances should result in {3} subnet counts")
    @MethodSource("testSubnetDistributionForWholeInstanceGroupWhen5InstancesWithPrepopulatedKnownSubnetIdData")
    public void testSubnetDistributionForWholeInstanceGroupWhen5InstancesWithPrepopulatedKnownSubnetId(CloudPlatform cloudPlatform, int subnetCount,
            int instanceCount, List<Long> expectedCounts, boolean supported) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        Set<InstanceMetaData> extraInstancesWithPrepopulatedSubnetId = new HashSet<>();
        String subnetIdForExtraInstances = cloudSubnetName(0);
        String availabilityZoneForExtraInstances = cloudSubnetAz(0);
        if (subnetCount > 0) {
            for (int i = 0; i < 5; i++) {
                extraInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + i, subnetIdForExtraInstances, availabilityZoneForExtraInstances,
                        null));
            }
        }
        instanceGroup.addAllInstanceMetadata(extraInstancesWithPrepopulatedSubnetId);

        // until the InstanceGroups are not refactored completly, we need the cast
        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                (InstanceGroup) instanceGroup.getInstanceGroup());

        List<Long> actualCounts = new ArrayList<>();
        for (int i = 0; i < subnetCount; i++) {
            int finalI = i;
            actualCounts.add(instanceGroup.getInstanceMetadataViews()
                    .stream()
                    .filter(instance -> instance.getSubnetId().equals(cloudSubnetName(finalI)))
                    .count());
        }
        Collections.sort(expectedCounts);
        Collections.sort(actualCounts);

        Assertions.assertEquals(expectedCounts, actualCounts);

        extraInstancesWithPrepopulatedSubnetId.forEach(instance -> {
            assertThat(instance.getSubnetId()).isEqualTo(subnetIdForExtraInstances);
            assertThat(instance.getAvailabilityZone()).isEqualTo(availabilityZoneForExtraInstances);
        });
    }

    @ParameterizedTest(name = "testSubnetDistributionForWholeInstanceGroupWhenDeletedInstances " +
            "with {0} platform when {1} subnets and {2} instances should result in {3} subnet counts")
    @MethodSource("testSubnetDistributionForWholeInstanceGroupData")
    public void testSubnetDistributionForWholeInstanceGroupWhenDeletedInstances(CloudPlatform cloudPlatform, int subnetCount, int instanceCount,
            List<Long> expectedCounts, boolean supported) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        Set<InstanceMetaData> deletedInstancesWithPrepopulatedSubnetId = new HashSet<>();
        String subnetIdForDeletedInstances = cloudSubnetName(0);
        String availabilityZoneForDeletedInstances = cloudSubnetAz(0);
        if (subnetCount > 0) {
            InstanceMetaData instanceWithTerminationDate = instanceMetaData(instanceCount, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    null);
            instanceWithTerminationDate.setTerminationDate(1234L);
            deletedInstancesWithPrepopulatedSubnetId.add(instanceWithTerminationDate);
            deletedInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + 1, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    InstanceStatus.TERMINATED));
            deletedInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + 2, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    InstanceStatus.DELETED_BY_PROVIDER));
            deletedInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + 3, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    InstanceStatus.DELETED_ON_PROVIDER_SIDE));
        }
        instanceGroup.getInstanceMetadataViews().addAll(deletedInstancesWithPrepopulatedSubnetId);

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                (InstanceGroup) instanceGroup.getInstanceGroup());

        List<Long> actualCounts = new ArrayList<>();
        for (int i = 0; i < subnetCount; i++) {
            int finalI = i;
            actualCounts.add(instanceGroup.getInstanceMetadataViews()
                    .stream()
                    .filter(instance -> instance.getSubnetId().equals(cloudSubnetName(finalI)))
                    .filter(instance -> !deletedInstancesWithPrepopulatedSubnetId.contains(instance))
                    .count());
        }
        Collections.sort(expectedCounts);
        Collections.sort(actualCounts);

        Assertions.assertEquals(expectedCounts, actualCounts);

        deletedInstancesWithPrepopulatedSubnetId.forEach(instance -> {
            assertThat(instance.getSubnetId()).isEqualTo(subnetIdForDeletedInstances);
            assertThat(instance.getAvailabilityZone()).isEqualTo(availabilityZoneForDeletedInstances);
        });
    }

    static Object[][] calculateByRoundRobinTestWhenWholeInstanceGroupAndNoSubnetIdsDataProvider() {
        return new Object[][]{
                // testCaseName disableNetwork disableAttributes disableSubnetIdsAttribute
                {"instanceGroupNetwork=null", true, false, false},
                {"attributes=null", false, true, false},
                {"subnetIdsAttribute=null", false, false, true},
                {"subnetIds=empty", false, false, false},
        };
    }

    @ParameterizedTest(name = "{0}")
    @MethodSource("calculateByRoundRobinTestWhenWholeInstanceGroupAndNoSubnetIdsDataProvider")
    void calculateByRoundRobinTestWhenWholeInstanceGroupAndNoSubnetIds(String testCaseName, boolean disableNetwork, boolean disableAttributes,
            boolean disableSubnetIdsAttribute) {
        InstanceGroupDto instanceGroupDto = instanceGroup(CloudPlatform.AWS, SINGLE_INSTANCE, NO_SUBNETS);
        InstanceGroup instanceGroup = (InstanceGroup) instanceGroupDto.getInstanceGroup();
        if (disableNetwork) {
            instanceGroup.setInstanceGroupNetwork(null);
        } else if (disableAttributes) {
            instanceGroup.getInstanceGroupNetwork().setAttributes(null);
        } else if (disableSubnetIdsAttribute) {
            instanceGroup.getInstanceGroupNetwork().setAttributes(new Json(Map.of()));
        }

        underTest.calculateByRoundRobin(
                subnetAzPairs(NO_SUBNETS),
                instanceGroup);

        instanceGroupDto.getInstanceMetadataViews().forEach(instance -> {
            assertThat(instance.getSubnetId()).isNull();
            assertThat(instance.getAvailabilityZone()).isNull();
        });
    }

    static Object[][] calculateByRoundRobinTestWhenCloudInstanceData() {
        return new Object[][]{
                // cloudPlatform, subnetCount, instanceCount, existingCounts, supported, expectedPermissibleSubnetIdIndexes
                {CloudPlatform.YARN, 0, 0, List.of(), false, Set.of()},
                {CloudPlatform.AWS, 1, 0, List.of(), true, Set.of(0)},
                {CloudPlatform.AWS, 1, 1, List.of(1), true, Set.of(0)},
                {CloudPlatform.AWS, 1, 2, List.of(2), true, Set.of(0)},
                {CloudPlatform.AWS, 2, 0, List.of(), true, Set.of(0, 1)},
                {CloudPlatform.AWS, 2, 1, List.of(1, 0), true, Set.of(1)},
                {CloudPlatform.AWS, 2, 1, List.of(0, 1), true, Set.of(0)},
                {CloudPlatform.AWS, 2, 2, List.of(2, 0), true, Set.of(1)},
                {CloudPlatform.AWS, 2, 2, List.of(1, 1), true, Set.of(0, 1)},
                {CloudPlatform.AWS, 2, 2, List.of(0, 2), true, Set.of(0)},
                {CloudPlatform.AWS, 2, 3, List.of(3, 0), true, Set.of(1)},
                {CloudPlatform.AWS, 2, 3, List.of(0, 3), true, Set.of(0)},
                {CloudPlatform.AWS, 2, 3, List.of(2, 1), true, Set.of(1)},
                {CloudPlatform.AWS, 2, 3, List.of(1, 2), true, Set.of(0)},
                {CloudPlatform.AWS, 3, 0, List.of(), true, Set.of(0, 1, 2)},
                {CloudPlatform.AWS, 3, 1, List.of(1, 0, 0), true, Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 1, List.of(0, 1, 0), true, Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 1, List.of(0, 0, 1), true, Set.of(0, 1)},
                {CloudPlatform.AWS, 3, 2, List.of(2, 0, 0), true, Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 2, List.of(0, 2, 0), true, Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 2, List.of(0, 0, 2), true, Set.of(0, 1)},
                {CloudPlatform.AWS, 3, 2, List.of(1, 1, 0), true, Set.of(2)},
                {CloudPlatform.AWS, 3, 2, List.of(0, 1, 1), true, Set.of(0)},
                {CloudPlatform.AWS, 3, 2, List.of(1, 0, 1), true, Set.of(1)},
                {CloudPlatform.AWS, 3, 3, List.of(3, 0, 0), true, Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 3, List.of(0, 3, 0), true, Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 3, List.of(0, 0, 3), true, Set.of(0, 1)},
                {CloudPlatform.AWS, 3, 3, List.of(2, 1, 0), true, Set.of(2)},
                {CloudPlatform.AWS, 3, 3, List.of(0, 1, 2), true, Set.of(0)},
                {CloudPlatform.AWS, 3, 3, List.of(2, 0, 1), true, Set.of(1)},
                {CloudPlatform.AWS, 3, 3, List.of(1, 1, 1), true, Set.of(0, 1, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(4, 0, 0), true, Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 4, 0), true, Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 0, 4), true, Set.of(0, 1)},
                {CloudPlatform.AWS, 3, 4, List.of(3, 1, 0), true, Set.of(2)},
                {CloudPlatform.AWS, 3, 4, List.of(1, 3, 0), true, Set.of(2)},
                {CloudPlatform.AWS, 3, 4, List.of(3, 0, 1), true, Set.of(1)},
                {CloudPlatform.AWS, 3, 4, List.of(1, 0, 3), true, Set.of(1)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 3, 1), true, Set.of(0)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 1, 3), true, Set.of(0)},
                {CloudPlatform.AWS, 3, 4, List.of(2, 2, 0), true, Set.of(2)},
                {CloudPlatform.AWS, 3, 4, List.of(2, 0, 2), true, Set.of(1)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 2, 2), true, Set.of(0)},
                {CloudPlatform.AWS, 3, 4, List.of(2, 1, 1), true, Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(1, 2, 1), true, Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(1, 1, 2), true, Set.of(0, 1)},
        };
    }

    @ParameterizedTest(name = "calculateByRoundRobinTestWhenCloudInstance " +
            "with {0} platform when {1} subnets and {2} instances and {3} subnet counts should result in {5} subnet / AZ")
    @MethodSource("calculateByRoundRobinTestWhenCloudInstanceData")
    public void calculateByRoundRobinTestWhenCloudInstance(CloudPlatform cloudPlatform, int subnetCount, int instanceCount, List<Integer> existingCounts,
            boolean supported, Set<Integer> expectedPermissibleSubnetIdIndexes) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        initSubnetIdAndAvailabilityZoneForInstances(existingCounts, instanceGroup);

        InstanceMetaData instanceMetaData = new InstanceMetaData();

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                instanceGroup,
                instanceMetaData,
                NetworkScaleDetails.getEmpty());

        verifyCloudInstance(expectedPermissibleSubnetIdIndexes, instanceMetaData);
        verifySubnetIdAndAvailabilityZoneForInstancesAreUnchanged(existingCounts, instanceGroup, Set.of());
    }

    @ParameterizedTest(name = "calculateByRoundRobinTestWhenCloudInstanceAndForeignSubnetId " +
            "with {0} platform when {1} subnets and {2} instances and {3} subnet counts should result in {5} subnet / AZ")
    @MethodSource("calculateByRoundRobinTestWhenCloudInstanceData")
    public void calculateByRoundRobinTestWhenCloudInstanceAndForeignSubnetId(CloudPlatform cloudPlatform, int subnetCount, int instanceCount,
            List<Integer> existingCounts, boolean supported, Set<Integer> expectedPermissibleSubnetIdIndexes) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        initSubnetIdAndAvailabilityZoneForInstances(existingCounts, instanceGroup);
        InstanceMetaData instanceWithPrepopulatedForeignSubnetId = instanceMetaData(instanceCount, SUBNET_ID, AVAILABILITY_ZONE, InstanceStatus.REQUESTED);
        instanceGroup.getInstanceMetadataViews().add(instanceWithPrepopulatedForeignSubnetId);

        InstanceMetaData instanceMetaData = new InstanceMetaData();
        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                instanceGroup,
                instanceMetaData,
                NetworkScaleDetails.getEmpty());

        verifyCloudInstance(expectedPermissibleSubnetIdIndexes, instanceMetaData);
        verifySubnetIdAndAvailabilityZoneForInstancesAreUnchanged(existingCounts, instanceGroup, Set.of(instanceWithPrepopulatedForeignSubnetId));

        assertThat(instanceWithPrepopulatedForeignSubnetId.getSubnetId()).isEqualTo(SUBNET_ID);
        assertThat(instanceWithPrepopulatedForeignSubnetId.getAvailabilityZone()).isEqualTo(AVAILABILITY_ZONE);
    }

    @ParameterizedTest(name = "calculateByRoundRobinTestWhenCloudInstanceAndDeletedInstances " +
            "with {0} platform when {1} subnets and {2} instances and {3} subnet counts should result in {5} subnet / AZ")
    @MethodSource("calculateByRoundRobinTestWhenCloudInstanceData")
    public void calculateByRoundRobinTestWhenCloudInstanceAndDeletedInstances(CloudPlatform cloudPlatform, int subnetCount, int instanceCount,
            List<Integer> existingCounts, boolean supported, Set<Integer> expectedPermissibleSubnetIdIndexes) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroupView.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        initSubnetIdAndAvailabilityZoneForInstances(existingCounts, instanceGroup);
        Set<InstanceMetaData> deletedInstancesWithPrepopulatedSubnetId = new HashSet<>();
        String subnetIdForDeletedInstances = cloudSubnetName(0);
        String availabilityZoneForDeletedInstances = cloudSubnetAz(0);
        if (subnetCount > 0) {
            InstanceMetaData instanceWithTerminationDate = instanceMetaData(instanceCount, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    null);
            instanceWithTerminationDate.setTerminationDate(1234L);
            deletedInstancesWithPrepopulatedSubnetId.add(instanceWithTerminationDate);
            deletedInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + 1, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    InstanceStatus.ZOMBIE));
            deletedInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + 2, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    InstanceStatus.DELETED_BY_PROVIDER));
            deletedInstancesWithPrepopulatedSubnetId.add(instanceMetaData(instanceCount + 3, subnetIdForDeletedInstances, availabilityZoneForDeletedInstances,
                    InstanceStatus.DELETED_ON_PROVIDER_SIDE));
        }
        instanceGroup.getInstanceMetadataViews().addAll(deletedInstancesWithPrepopulatedSubnetId);

        InstanceMetaData instanceMetaData = new InstanceMetaData();

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                instanceGroup,
                instanceMetaData,
                NetworkScaleDetails.getEmpty());

        verifyCloudInstance(expectedPermissibleSubnetIdIndexes, instanceMetaData);
        verifySubnetIdAndAvailabilityZoneForInstancesAreUnchanged(existingCounts, instanceGroup, deletedInstancesWithPrepopulatedSubnetId);

        deletedInstancesWithPrepopulatedSubnetId.forEach(instance -> {
            assertThat(instance.getSubnetId()).isEqualTo(subnetIdForDeletedInstances);
            assertThat(instance.getAvailabilityZone()).isEqualTo(availabilityZoneForDeletedInstances);
        });
    }

    static Object[][] calculateByRoundRobinTestWhenCloudInstanceAndNoSubnetIdsDataProvider() {
        return new Object[][]{
                // testCaseName disableNetwork disableAttributes disableSubnetIdsAttribute prepopulateCloudInstanceSubnet
                {"instanceGroupNetwork=null, prepopulateCloudInstanceSubnet=false", true, false, false, false},
                {"instanceGroupNetwork=null, prepopulateCloudInstanceSubnet=true", true, false, false, true},
                {"attributes=null, prepopulateCloudInstanceSubnet=false", false, true, false, false},
                {"attributes=null, prepopulateCloudInstanceSubnet=true", false, true, false, true},
                {"subnetIdsAttribute=null, prepopulateCloudInstanceSubnet=false", false, false, true, false},
                {"subnetIdsAttribute=null, prepopulateCloudInstanceSubnet=true", false, false, true, true},
                {"subnetIds=empty, prepopulateCloudInstanceSubnet=false", false, false, false, false},
                {"subnetIds=empty, prepopulateCloudInstanceSubnet=true", false, false, false, true},
        };
    }

    @ParameterizedTest(name = "{0}")
    @MethodSource("calculateByRoundRobinTestWhenCloudInstanceAndNoSubnetIdsDataProvider")
    void calculateByRoundRobinTestWhenCloudInstanceAndNoSubnetIds(String testCaseName, boolean disableNetwork, boolean disableAttributes,
            boolean disableSubnetIdsAttribute, boolean prepopulateCloudInstanceSubnet) {
        InstanceGroupDto instanceGroup = instanceGroup(CloudPlatform.AWS, SINGLE_INSTANCE, NO_SUBNETS);
        if (disableNetwork) {
            ((InstanceGroup) instanceGroup.getInstanceGroup()).setInstanceGroupNetwork(null);
        } else if (disableAttributes) {
            ((InstanceGroup) instanceGroup.getInstanceGroup()).getInstanceGroupNetwork().setAttributes(null);
        } else if (disableSubnetIdsAttribute) {
            ((InstanceGroup) instanceGroup.getInstanceGroup()).getInstanceGroupNetwork().setAttributes(new Json(Map.of()));
        }

        String cloudInstanceSubnetId = prepopulateCloudInstanceSubnet ? SUBNET_ID : null;
        String cloudInstanceAvailabilityZone = prepopulateCloudInstanceSubnet ? AVAILABILITY_ZONE : null;
        InstanceMetaData instanceMetaData = new InstanceMetaData();
        instanceMetaData.setSubnetId(cloudInstanceSubnetId);
        instanceMetaData.setAvailabilityZone(cloudInstanceAvailabilityZone);

        underTest.calculateByRoundRobin(
                subnetAzPairs(NO_SUBNETS),
                instanceGroup,
                instanceMetaData,
                NetworkScaleDetails.getEmpty());

        verifyCloudInstance(cloudInstanceSubnetId == null ? Set.of() : Set.of(cloudInstanceSubnetId),
                cloudInstanceAvailabilityZone == null ? Set.of() : Set.of(cloudInstanceAvailabilityZone),
                instanceMetaData);

        instanceGroup.getInstanceMetadataViews().forEach(instance -> {
            assertThat(instance.getSubnetId()).isNull();
            assertThat(instance.getAvailabilityZone()).isNull();
        });
    }

    @Test
    public void calculateByRoundRobinTestWhenCloudInstanceAndPrepopulatedCloudInstanceSubnet() {
        when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);

        List<Integer> existingCounts = List.of(SINGLE_SUBNET);
        InstanceGroupDto instanceGroup = instanceGroup(CloudPlatform.AWS, SINGLE_INSTANCE, SINGLE_SUBNET);
        initSubnetIdAndAvailabilityZoneForInstances(existingCounts, instanceGroup);

        InstanceMetaData instanceMetaData = new InstanceMetaData();
        instanceMetaData.setSubnetId(SUBNET_ID);
        instanceMetaData.setAvailabilityZone(AVAILABILITY_ZONE);

        underTest.calculateByRoundRobin(
                subnetAzPairs(SINGLE_SUBNET),
                instanceGroup,
                instanceMetaData,
                NetworkScaleDetails.getEmpty());

        verifyCloudInstance(Set.of(SUBNET_ID), Set.of(AVAILABILITY_ZONE), instanceMetaData);
        verifySubnetIdAndAvailabilityZoneForInstancesAreUnchanged(existingCounts, instanceGroup, Set.of());
    }

    static Object[][] calculateByRoundRobinTestWhenCloudInstanceAndInstancesWithoutSubnetData() {
        return new Object[][]{
                // cloudPlatform, subnetCount, instanceCount, supported, expectedPermissibleSubnetIdIndexes
                {CloudPlatform.YARN, 0, 0, false, Set.of()},
                {CloudPlatform.AWS, 1, 0, true, Set.of(0)},
                {CloudPlatform.AWS, 1, 1, true, Set.of(0)},
                {CloudPlatform.AWS, 1, 2, true, Set.of(0)},
                {CloudPlatform.AWS, 2, 0, true, Set.of(0, 1)},
                {CloudPlatform.AWS, 2, 1, true, Set.of(0, 1)},
                {CloudPlatform.AWS, 2, 2, true, Set.of(0, 1)},
                {CloudPlatform.AWS, 2, 3, true, Set.of(0, 1)},
                {CloudPlatform.AWS, 3, 0, true, Set.of(0, 1, 2)},
                {CloudPlatform.AWS, 3, 1, true, Set.of(0, 1, 2)},
                {CloudPlatform.AWS, 3, 2, true, Set.of(0, 1, 2)},
                {CloudPlatform.AWS, 3, 3, true, Set.of(0, 1, 2)},
                {CloudPlatform.AWS, 3, 4, true, Set.of(0, 1, 2)},
        };
    }

    @ParameterizedTest(name = "calculateByRoundRobinTestWhenCloudInstanceAndInstancesWithoutSubnet " +
            "with {0} platform when {1} subnets and {2} instances and {3} subnet counts should result in {5} subnet / AZ")
    @MethodSource("calculateByRoundRobinTestWhenCloudInstanceAndInstancesWithoutSubnetData")
    public void calculateByRoundRobinTestWhenCloudInstanceAndInstancesWithoutSubnet(CloudPlatform cloudPlatform, int subnetCount, int instanceCount,
            boolean supported, Set<Integer> expectedPermissibleSubnetIdIndexes) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);

        InstanceMetaData instanceMetaData = new InstanceMetaData();

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                instanceGroup,
                instanceMetaData,
                NetworkScaleDetails.getEmpty());

        verifyCloudInstance(expectedPermissibleSubnetIdIndexes, instanceMetaData);

        instanceGroup.getInstanceMetadataViews().forEach(instance -> {
            assertThat(instance.getSubnetId()).isNull();
            assertThat(instance.getAvailabilityZone()).isNull();
        });
    }

    static Object[][] determineRackIdTestDataProvider() {
        return new Object[][]{
                // testCaseName subnetId availabilityZone rackIdExpected
                {"subnetId=null, availabilityZone=null", null, null, "/default-rack"},
                {"subnetId=\"\", availabilityZone=null", "", null, "/default-rack"},
                {"subnetId=null, availabilityZone=\"\"", null, "", "/default-rack"},
                {"subnetId=\"\", availabilityZone=\"\"", "", "", "/default-rack"},
                {"subnetId=SUBNET_ID, availabilityZone=null", SUBNET_ID, null, "/SUBNET_ID"},
                {"subnetId=SUBNET_ID, availabilityZone=\"\"", SUBNET_ID, "", "/SUBNET_ID"},
                {"subnetId=null, availabilityZone=AVAILABILITY_ZONE", null, AVAILABILITY_ZONE, "/AVAILABILITY_ZONE"},
                {"subnetId=\"\", availabilityZone=AVAILABILITY_ZONE", "", AVAILABILITY_ZONE, "/AVAILABILITY_ZONE"},
                {"subnetId=SUBNET_ID, availabilityZone=AVAILABILITY_ZONE", SUBNET_ID, AVAILABILITY_ZONE, "/AVAILABILITY_ZONE"},
        };
    }

    @ParameterizedTest(name = "saveInstanceMetaDataTestDataProvider {0}")
    @MethodSource("determineRackIdTestDataProvider")
    void determineRackIdTest(String testCaseName, String subnetId, String availabilityZone, String rackIdExpected) {
        String rackId = underTest.determineRackId(subnetId, availabilityZone);

        assertThat(rackId).isEqualTo(rackIdExpected);
    }

    static Object[][] calculateByRoundRobinTestWhenCloudInstanceDataAndPreferredAvailabilityZones() {
        return new Object[][]{
                // cloudPlatform, subnetCount, instanceCount, existingCounts, supported, expectedPermissibleSubnetIdIndexes, PreferredSubnetIdIndexes
                {CloudPlatform.AWS, 1, 0, List.of(), true, Set.of(0), Set.of()},
                {CloudPlatform.AWS, 1, 1, List.of(1), true, Set.of(0), Set.of(0)},
                {CloudPlatform.AWS, 1, 2, List.of(2), true, Set.of(0), Set.of(0)},
                {CloudPlatform.AWS, 2, 2, List.of(1, 1), true, Set.of(0, 1), Set.of()},
                {CloudPlatform.AWS, 2, 2, List.of(1, 1), true, Set.of(1), Set.of(1)},
                {CloudPlatform.AWS, 3, 0, List.of(), true, Set.of(0, 2), Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 1, List.of(1, 0, 0), true, Set.of(1, 2), Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 1, List.of(0, 1, 0), true, Set.of(2), Set.of(2)},
                {CloudPlatform.AWS, 3, 1, List.of(0, 0, 1), true, Set.of(0), Set.of(0)},
                {CloudPlatform.AWS, 3, 2, List.of(2, 0, 0), true, Set.of(1, 2), Set.of()},
                {CloudPlatform.AWS, 3, 4, List.of(4, 0, 0), true, Set.of(0), Set.of(0)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 4, 0), true, Set.of(2), Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(0, 0, 4), true, Set.of(0), Set.of(0, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(2, 1, 1), true, Set.of(1, 2), Set.of(1, 2)},
                {CloudPlatform.AWS, 3, 4, List.of(1, 2, 1), true, Set.of(2), Set.of(2)},
                {CloudPlatform.AWS, 3, 4, List.of(1, 1, 2), true, Set.of(2), Set.of(2)},
        };
    }

    @ParameterizedTest(name = "calculateByRoundRobinTestWhenCloudInstance " +
            "with {0} platform when {1} subnets, {2} instances, {3} subnet counts and preferred subnets {6} should result in {5} subnet / AZ")
    @MethodSource("calculateByRoundRobinTestWhenCloudInstanceDataAndPreferredAvailabilityZones")
    public void calculateByRoundRobinTestWhenCloudInstanceAndPreferredAvailabilityZones(CloudPlatform cloudPlatform, int subnetCount, int instanceCount,
            List<Integer> existingCounts, boolean supported, Set<Integer> expectedPermissibleSubnetIdIndexes, Set<Integer> preferredSubnetIdIndexes) {
        if (supported) {
            when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        }

        InstanceGroupDto instanceGroup = instanceGroup(cloudPlatform, instanceCount, subnetCount);
        initSubnetIdAndAvailabilityZoneForInstances(existingCounts, instanceGroup);

        InstanceMetaData instanceMetaData = new InstanceMetaData();

        List<String> preferredSubnetIds = preferredSubnetIdIndexes.stream()
                .map(index -> cloudSubnet(index).getName())
                .collect(Collectors.toList());
        NetworkScaleDetails networkScaleDetails = new NetworkScaleDetails(preferredSubnetIds);

        underTest.calculateByRoundRobin(
                subnetAzPairs(subnetCount),
                instanceGroup,
                instanceMetaData,
                networkScaleDetails);

        verifyCloudInstance(expectedPermissibleSubnetIdIndexes, instanceMetaData);
        verifySubnetIdAndAvailabilityZoneForInstancesAreUnchanged(existingCounts, instanceGroup, Set.of());
    }

    @Test
    public void testWhenNoAvailableSubnetInTheEnvironmentByInstanceGroup() {
        when(multiAzValidator.supportedForInstanceMetadataGeneration(any(InstanceGroup.class))).thenReturn(true);
        InstanceGroupDto instanceGroup = instanceGroup(CloudPlatform.AWS, SINGLE_INSTANCE, SINGLE_SUBNET);

        InstanceMetaData instanceMetaData = new InstanceMetaData();
        instanceMetaData.setSubnetId(SUBNET_ID);
        instanceMetaData.setAvailabilityZone(AVAILABILITY_ZONE);
        CloudbreakServiceException actual = Assertions.assertThrows(CloudbreakServiceException.class, () ->
                underTest.calculateByRoundRobin(Map.of("anysubnet", "anyaz"), instanceGroup, instanceMetaData, NetworkScaleDetails.getEmpty()));
        assertThat(actual.getMessage()).isEqualTo("The following subnets are missing from the Environment, you may have removed them during an environment " +
                "update previously? Missing subnets: [name-0]");
    }

    private InstanceGroupDto instanceGroup(CloudPlatform cloudPlatform, int instanceNumber, int subnetCount) {
        InstanceGroup instanceGroup = new InstanceGroup();
        List<String> subnets = new ArrayList<>();
        for (int i = 0; i < subnetCount; i++) {
            instanceGroup.getAvailabilityZones().add(cloudSubnetAz(i));
            subnets.add(cloudSubnetName(i));
        }
        InstanceGroupNetwork instanceGroupNetwork = new InstanceGroupNetwork();
        instanceGroupNetwork.setCloudPlatform(cloudPlatform.name());
        instanceGroupNetwork.setAttributes(new Json(Map.of(NetworkConstants.SUBNET_IDS, subnets)));
        instanceGroup.setInstanceGroupNetwork(instanceGroupNetwork);
        for (int i = 0; i < instanceNumber; i++) {
            instanceGroup.getAllInstanceMetaData().add(instanceMetaData(i));
        }
        return new InstanceGroupDto(instanceGroup, new ArrayList<>(instanceGroup.getAllInstanceMetaData()));
    }

    private InstanceMetaData instanceMetaData(int i, String subnetId, String availabilityZone, InstanceStatus instanceStatus) {
        InstanceMetaData instance = instanceMetaData(i);
        instance.setSubnetId(subnetId);
        instance.setAvailabilityZone(availabilityZone);
        instance.setInstanceStatus(instanceStatus);
        return instance;
    }

    private InstanceMetaData instanceMetaData(int i) {
        InstanceMetaData instanceMetaData = new InstanceMetaData();
        instanceMetaData.setId((long) i);
        return instanceMetaData;
    }

    private Map<String, String> subnetAzPairs(int subnetCount) {
        Map<String, String> subnetAzPairs = new HashMap<>();
        for (int i = 0; i < subnetCount; i++) {
            subnetAzPairs.put(cloudSubnetName(i), cloudSubnetAz(i));
        }
        return subnetAzPairs;
    }

    private CloudSubnet cloudSubnet(int i) {
        CloudSubnet cloudSubnet = new CloudSubnet();
        cloudSubnet.setId(String.valueOf(i));
        cloudSubnet.setName(cloudSubnetName(i));
        cloudSubnet.setAvailabilityZone(cloudSubnetAz(i));
        return cloudSubnet;
    }

    private String cloudSubnetName(int i) {
        return "name-" + i;
    }

    private String cloudSubnetAz(int i) {
        return "az-" + i;
    }

    private void initSubnetIdAndAvailabilityZoneForInstances(List<Integer> existingCounts, InstanceGroupDto instanceGroup) {
        int totalExistingCount = existingCounts.stream()
                .mapToInt(Integer::intValue)
                .sum();
        Queue<Integer> existingSubnetIdIndexes = new ArrayDeque<>(totalExistingCount);
        int existingSubnetIdIndex = 0;
        for (int count : existingCounts) {
            for (int i = 0; i < count; i++) {
                existingSubnetIdIndexes.add(existingSubnetIdIndex);
            }
            existingSubnetIdIndex++;
        }
        instanceGroup.getInstanceMetadataViews().forEach(instance -> {
            Integer subnetIdIndex = existingSubnetIdIndexes.poll();
            if (subnetIdIndex != null) {
                ((InstanceMetaData) instance).setSubnetId(cloudSubnetName(subnetIdIndex));
                ((InstanceMetaData) instance).setAvailabilityZone(cloudSubnetAz(subnetIdIndex));
            }
        });
    }

    private void verifyCloudInstance(Set<Integer> expectedPermissibleSubnetIdIndexes, InstanceMetaData instanceMetaData) {
        Set<String> expectedPermissibleSubnetIds = null;
        Set<String> expectedPermissibleAvailabilityZones = null;
        if (!CollectionUtils.isEmpty(expectedPermissibleSubnetIdIndexes)) {
            expectedPermissibleSubnetIds = expectedPermissibleSubnetIdIndexes.stream()
                    .map(this::cloudSubnetName)
                    .collect(Collectors.toSet());
            expectedPermissibleAvailabilityZones = expectedPermissibleSubnetIdIndexes.stream()
                    .map(this::cloudSubnetAz)
                    .collect(Collectors.toSet());
        }

        verifyCloudInstance(expectedPermissibleSubnetIds, expectedPermissibleAvailabilityZones, instanceMetaData);
    }

    private void verifyCloudInstance(Set<String> expectedPermissibleSubnetIds, Set<String> expectedPermissibleAvailabilityZones,
            InstanceMetaData instanceMetaData) {
        if (CollectionUtils.isEmpty(expectedPermissibleSubnetIds)) {
            assertThat(instanceMetaData.getSubnetId()).isNull();
        } else {
            assertThat(instanceMetaData.getSubnetId()).isIn(expectedPermissibleSubnetIds);
        }

        if (CollectionUtils.isEmpty(expectedPermissibleAvailabilityZones)) {
            assertThat(instanceMetaData.getAvailabilityZone()).isNull();
        } else {
            assertThat(instanceMetaData.getAvailabilityZone()).isIn(expectedPermissibleAvailabilityZones);
        }
    }

    private void verifySubnetIdAndAvailabilityZoneForInstancesAreUnchanged(List<Integer> existingCounts, InstanceGroupDto instanceGroup,
            Set<InstanceMetaData> instancesToIgnore) {
        int countNum = existingCounts.size();
        Map<String, Integer> subnetIdToIndexMap = new HashMap<>(countNum);
        Map<String, Integer> availabilityZoneToIndexMap = new HashMap<>(countNum);
        for (int i = 0; i < countNum; i++) {
            subnetIdToIndexMap.put(cloudSubnetName(i), i);
            availabilityZoneToIndexMap.put(cloudSubnetAz(i), i);
        }

        Integer[] actualCountsArray = new Integer[countNum];
        Arrays.fill(actualCountsArray, 0);
        instanceGroup.getInstanceMetadataViews().forEach(instance -> {
            if (!instancesToIgnore.contains(instance)) {
                Integer subnetIdIndex = subnetIdToIndexMap.get(instance.getSubnetId());
                Integer availabilityZoneIndex = availabilityZoneToIndexMap.get(instance.getAvailabilityZone());
                assertThat(subnetIdIndex).isNotNull();
                assertThat(subnetIdIndex).isEqualTo(availabilityZoneIndex);
                actualCountsArray[subnetIdIndex]++;
            }
        });
        assertThat(Arrays.asList(actualCountsArray)).isEqualTo(existingCounts);
    }

}

redpajama_set_name: RedPajamaGithub


text:
The Propaganda Poster Art Centre ( or ) is a museum located in Shanghai which exhibits posters from the Maoist period of communist China, especially from the Cultural Revolution period. The museum was located in the basement of an apartment building in Huashan Road facing Wukang Road, in the former French Concession area until 2019 when it relocated to an office building on Yan'an West Road.  It has a rich collection of rare last-piece posters.

The owner of the museum, Mr. Yang Pei Ming, is keeping the posters as they are to be seen as an art form. He started collecting the posters as a hobby in 1995, and he wants to preserve the posters for the future. The museum is visited mainly by tourists, as it is listed in guides such as Lonely Planet and Frommers.

References

External links

 Official website

Museums in Shanghai
Propaganda in China
Art museums and galleries in China
Poster museums

redpajama_set_name: RedPajamaWikipedia


My father wasn't in the army because he had a bad heart. So what is he doing in these uniforms? He was in the CCC's (Civilian Conservation Corps.). But I don't think they wore uniforms like this. And why would he have a rifle with a bayonet?
I posted these pictures a while back and I think I asked the same question. Maybe this time someone will come up with an answer.
Nancy brought a pot of soup over that she made with my left-over chicken carcass. We were going to have it after she drove me to the eye doctor and we did some shopping.
It was cooking all morning while I was at my art class.
We left for the eye doctor, got a few miles and Nancy remembered that she hadn't turned off the stove. We went back and I ran in and turned it off. We were gone about 3 hours. Came back to a terrible smell. Lifted off the top of the pot to lots of smoke.
I'm not very familiar with my stove, as anyone who knows me, knows. But I still can't see how I did this. It must be my cataracts!
The house smelled so bad that we had to cancel our 4:00 social hour with Helen and Beth. It was the one cold day that we couldn't have sat out on the deck....hence the chicken soup.
It's been 4 days and the smell still hasn't gone away.
I wasn't sure if it was true that the painting which includes my ancestors (see previous post) was really on the back of the $10,000 bill, or if one really exists.
It is true. Apparently they're very rare and mostly only owned by collectors.
My ancestors Susanna and William White leaving Holland before their trip on the Mayflower.
Embarkation of the Pilgrims at Delft Haven, Holland, July 22, 1620, by Robert W. Weir. Oil on canvas, 12' x 18.' Located in the Capitol Rotunda. Placed December 21, 1843. In 1836, the United States government commissioned Robert W. Weir to paint The Picture of the Embarkation of the Pilgrims from Delft Haven in Holland "for filling the vacant panels in the rotunda of the Capital" in Washington, D.C. It was one of several large scale (12' x 18') paintings chosen to represent significant historical moments leading to the founding of the American Republic. Completed in 1843, it depicts the Pilgrim families gathered around their pastor, John Robinson, for a farewell service on the deck of the Speedwell before its departure from Holland. Weir worked on the Embarkation for over seven years. The left lower couple in the front, kneeling on the deck are depictions of Susanna and William White.
I just found this. I knew my great-great-great (etc,) grandparents came over on the Mayflower but I had no idea they were in a painting and that it is hanging in the Capitol.
Apparently it's also on the back of the U.S. $10,000 bill. I didn't know there was such a thing.


I am such a sucker for nice stationary it always makes me feel like I'm more prepared (whether I actually am or not is beside the point). Sometimes I go into stationary shops just to look at (oh, alright and touch) all the shiny new things and imagine what I could do if only I had more lovely pencils, pens and planners to do it with. With that note book I could take over the world! Perhaps not - but it does make me feel a bit special to put my to do lists down in my pretty new planner and tick the things off as I go.
At this point either you're with me on the stationary love or you're shaking your head thinking I need a hobby. Well, don't you judge - what's your poison?? Garden shops, nic-nac shops, shoe shops.... don't pretend you don't know what I'm talking about.
I was recently introduced to personal-planner.com.au and I have to say I LOVE the idea of being able to make your yearly planner a bit special and personal. Go check out their website at http://www.personal-planner.com.au/AU/ and see all the lovely things you can do with a planner. Their specially designed website enables you to change the colour, text and design on the front and back cover of your planner as well as inlay and choose the start date for your planner. There are also clever boxes for to-do list, gym session, preschool, idea of the week and weather. Friends and family member's birthdays can also be added to the inlay directly from Facebook! Actually you can go and say hi to them on Facebook here and make sure you like them while you are there. A lot of paper products you buy online now are e-products so you buy it and have to print it out at home yourself. The thing I love is that personal-planner.com.au print and deliver the finished product to you. Nice.
OK, so here's the thing - I need your help (it will be painless - I promise). In line with my vision to make 2013 something big and wonderful I have put together a short survey so I can get to know what you know and love and need more of to make Mother Load (and your world) even better. Just click and fill in the survey here. Now, here's the exciting part - I am not asking you to take a few minutes out of your life without thinking about how I can make your day nicer, so once you fill out the survey you go into the draw to win a planner from personal-planner.com.au . Yep, you heard it right! The winner will be chosen in two weeks time and will be announced in the blog post on Friday the 8th of February. The winner will be able to choose any planner in any size and the shipping is included!! Woo hoo!! I have already had friends ask me for this one! But the prize will be drawn fairly and taken from the list of people who fill out the survey. (You can get to the survey by clicking here).
I wanted to let you know that this post has been sponsored by personal-planner.com.au - not as in paid for but as in they have generously given me a planner and this prize to give to you and talk about it. Hey, it's stationary - not a hard ask for me.
So there it is my very first sponsored post, woo hoo - look at me go!!
Firstly, I wanted to let you know that because I am all about being open and honest with you and secondly I was quite excited about it. Mother Load started as me wanting to find some kind of purpose (let's call it retaining my sanity) and it has become something bigger than just myself and a handful of friends reading it. I have had comments on posts from all around the world (I can't tell you how exciting that is) from mums who are going through the very same things, or just letting me know that I made them laugh. How wonderful to know that we are not alone!
So go ahead and help me out and fill out the survey and throw your hat in the ring to win this awesome planner to plan out all the exciting things you are going to do this year... and so you don't forget anyone's birthday!! Now is the time to start getting your organisation on for 2013 (don't tell me you already let some of your New Year's Resolutions beat you).
Just in case you missed it the link to the survey is here and don't forget you can always subscribe to Mother Load with the little box up in the right hand side of the page and never miss a post!
oh no! I will check that straight away!!
Thanks - pretty excited about it myself! I knew I wasn't alone on the stationary love!
Congrats on great giveaway Lee! I'm totes usually in most areas of organisation but as my No.1 starts school this year I'll have to start right?!
At some stage yes. Now is as good a time as any - don't forget to fill out the survey (if you haven't already!) and get in the draw for that awesome planner!
I did the survey and I really want to win this planner! I have to admit that I'm not a regular visitor to your blog but I promise I'll try to come over here more often in the future.
Well good luck Rita - it's nice that you came by! And the planners are very cool so I get that.
We speak the same language! I am a complete stationary addict and nodded the whole way through your post.
Just discovered your blog via FYBF and will be back!
Thanks Carly - nice to know it wasn't just me then!
Hi, have just subscribed, congrats on the comp, looking forward to looking at all the info here on your blog!
Great giveaway!Have just filled out the survey for you too. Go, you!


A Family Stories Extravaganza at The Livery at Sunapee Harbor NH August 11!
Get your tickets now for Odds Bodkin's FAMILY STORIES EXTRAVAGANZA for this coming Friday night, August 11th! Hosted by The Livery at Sunapee Harbor , Odds' fingers will fly across his Celtic harp, 12-string guitars and other instruments as he tells his best, family friendly tales. Wild character voices, uncannily real vocal effects and narrative combine to create imagination entertainments parents and kids always love.
Called "a consummate storyteller" by The New York Times and "one of the great voices in American storytelling" by Wired, Odds invites you not only to listen, but to sing along if you like, create rhythms and simply have fun. Stories from all around the world with music to match!
Tickets are $10 adult, $5 children, $25 for family of 4 here.
Eclipse Tales south of Boston tomorrow at 3 pm!


Center panel - vertically seamed.
Contour/t-shirt wireless cups have light padding for shape and support.
Front adjustable shoulder straps. Contour/t-shirt wireless cups have light padding for shape and support.


In the first ever IYH Friday Night Special Jack and guest co-host Buck Winchester were joined by Team Elite Sonny Roselli and Larry Huntley. We went over their careers, how they broke into the business, working for New England and Canadian Indy promotions, driving the long roads, a brief TNA stint, road and rib stories, AWA, a possible revelation around the "retirement" of Steve Corino and much more !!!
Jack and Buck went over some of the wrestling news of the week in the pre and post interview segments. Check out what Buck has referred to as a "5 Star Classic", and that's out of 5 stars folks not 10. The IYH Friday Night Special !!!
The IYH crew went over RAW and ECW this week in a heated debate between Jack and his cohorts Barbie and Incher. Jack enjoyed RAW this week, while Incher and Barbie took the side of hatred and fear. Who was right ? Who was wrong ? Listen and decide for yourself !!
In the 2nd hour we were joined by Shawn Daivari in a very in depth 45 minute interview. We covered ROH, TNA and his stay in the WWE. Including managing Kurt Angle, Mark Henry, Khali and Hassan. Wanting to pursue a wrestling career, his Jillian Hall angle, wrestling Jim Duggan, HBK and Hulk Hogan. Being on Wrestle Mania, ECW, Smackdown and RAW. Why he left WWE, if he would come back, his views on the Cruiserweight Division and much more !!!
The Cuban Assassin Live Tonight !!!
New WYH Playing Listen Now !!!
Chris Jericho was our guest this week. We went over his autobiography "A Lion's Tale: Around The World In Spandex". We talked about his training with Lance Storm, SMW, Japan, Mexico, WCW, Ralphus and so much more !!!
In the pre interview portion the IYH Crew talked about RAW, Cyber Sunday, ECW Monster Bash Battle Royal and lots more.
So check it out Junior !!
YOU Choose The Guest This Wednesday !!!
Click the banner above to vote now !!!
The score must be settled.
Click the banner above to go to Neal's Sportswear 'N Stuff!!!


text:
Cornyn blames GOP Senate losses on polling, primary wins of weak candidates
By kyle.campbell@chron.com (Kyle Campbell) on November 15, 2012 at 1:15 PM
window._taboola = window._taboola || []; _taboola.push({ mode: 'thumbnails-c', container: 'taboola-interstitial-gallery-thumbnails-5', placement: 'Interstitial Gallery Thumbnails 5', target_type: 'mix' });
window._taboola = window._taboola || []; _taboola.push({ mode: 'thumbnails-c', container: 'taboola-interstitial-gallery-thumbnails-10', placement: 'Interstitial Gallery Thumbnails 10', target_type: 'mix' });
Image 1of/49
New Senate Minority whip John Cornyn of Texas, left, speaks during a news conference on Capitol Hill in Washington, Wednesday, Nov. 14, 2012. From left are, Cornyn, as Sen, John Barrasso, R-Wyo., John Thune, R-S.D., and Senate Minority Leader Mitch McConnell of Ky. (AP Photo/Harry Hamburg) less
New Senate Minority whip John Cornyn of Texas, left, speaks during a news conference on Capitol Hill in Washington, Wednesday, Nov. 14, 2012. From left are, Cornyn, as Sen, John Barrasso, R-Wyo., John Thune, ... more
WASHINGTON, DC - NOVEMBER 14: U.S. Sen. John Cornyn (R-TX) (L), speaks to the media while flanked by Senate Minority Leader Mitch McConnell (R-KY), on November 14, 2012 in Washington, DC. The Senators spoke briefly to reporters after attending a policy luncheon. (Photo by Mark Wilson/Getty Images) less
WASHINGTON, DC - NOVEMBER 14: U.S. Sen. John Cornyn (R-TX) (L), speaks to the media while flanked by Senate Minority Leader Mitch McConnell (R-KY), on November 14, 2012 in Washington, DC. The Senators spoke ... more
Senate Minority Leader Mitch McConnell of Ky., center, gesture during a news conference on Capitol Hill in Washington, Wednesday, Nov. 14, 2012. From left are, Sen. John Thune, R-S.D., McConnell, Sen. John Barrasso, R-Wyo., Jerry Moran, R-Kansas, and new Senate Minority Whip John Cornyn of Texas. (AP Photo/Harry Hamburg) less
Senate Minority Leader Mitch McConnell of Ky., center, gesture during a news conference on Capitol Hill in Washington, Wednesday, Nov. 14, 2012. From left are, Sen. John Thune, R-S.D., McConnell, Sen. John ... more
John Cornyn is interviewed after leaving the US Supreme Court in Washington, DC after the morning session March 27, 2012.
Photo: Karen Bleier / AFP/Getty Images
Sen. John Cornyn is interviewed after leaving the US Supreme Court in Washington, DC after the morning session March 27, 2012.
John Cornyn and John Kerry descend the steps of the US Supreme Court in Washington after the morning session on March 27, 2012.
Photo: Karen Bleier / Getty Images
Sen. John Cornyn, Sen. John Hoeven, R-N.D., and Sen. Richard Lugar, R-Ind. watch a monitor as President Barack Obama speaks about the Keystone XL pipeline live from Cushing, Okla., before their news conference on the same subject, Thursday, March 22, 2012, on Capitol Hill in Washington. less
Sen. John Cornyn, Sen. John Hoeven, R-N.D., and Sen. Richard Lugar, R-Ind. watch a monitor as President Barack Obama speaks about the Keystone XL pipeline live from Cushing, Okla., before their news conference ... more
Photo: Charles Dharapak / The Associated Press
President Barack Obama is seen on a television screen speaking live about the Keystone XL pipeline from Cushing, Okla., as Sen. John Cornyn, R-Texas, and Sen. John Hoeven, R-N.D. talk before the start of their news conference about the same oil pipeline, Thursday, March 22, 2012, on Capitol Hill in Washington. less
President Barack Obama is seen on a television screen speaking live about the Keystone XL pipeline from Cushing, Okla., as Sen. John Cornyn, R-Texas, and Sen. John Hoeven, R-N.D. talk before the start of their ... more
Sen. Lisa Murkowski, R-Ark., Sen. John Cornyn, R-Texas, David Vitter R-La., and Rep. Lee Terry, R-Neb., listen during a news conference March 22, 2012 on Capitol Hill in Washington, DC.
Photo: Alex Wong / Getty Images
Sen John Cornyn points to his lapel pin as he speaks about the Keystone XL pipeline during a news conference on Capitol Hill in Washington, Thursday, March 22, 2012.
Sen. Lisa Murkowski, R-Alaska, talks to Texas Sen. John Cornyn, John Hoeven, R-N.D., and John Thune, R-S.D., prior to a news conference on gas prices on Capitol Hill in Washington on Feb. 29, 2012.
Photo: Jacquelyn Martin / The Associated Press
Sen. John Cornyn, R-Texas, criticizes U.S. Attorney General Eric Holder as he speaks to activists from America's political right at the Conservative Political Action Conference (CPAC) in Washington, Saturday, Feb. 11, 2012. less
Sen. John Cornyn, R-Texas, criticizes U.S. Attorney General Eric Holder as he speaks to activists from America's political right at the Conservative Political Action Conference (CPAC) in Washington, Saturday, ... more
Photo: J. Scott Applewhite / The Associated Press
hJohn Cornyn questions Attorney General Eric Holder as the Senate Judiciary Committee investigates the controversial "Operation Fast and Furious" gunrunning program and how firearms wound up in the hands of Mexican drug cartels, on Capitol Hill in Washington, Tuesday, Nov. 8, 2011. less
hJohn Cornyn questions Attorney General Eric Holder as the Senate Judiciary Committee investigates the controversial "Operation Fast and Furious" gunrunning program and how firearms wound up in the hands ... more
In this file photo, Defense Secretary of Defense nominee, CIA Director Leon Panetta, is greeted on Capitol Hill in Washington by Sen. John Cornyn as he arrived to testify before a Senate Armed Service Committee hearing on his nomination on June 9, 2011 less
In this file photo, Defense Secretary of Defense nominee, CIA Director Leon Panetta, is greeted on Capitol Hill in Washington by Sen. John Cornyn as he arrived to testify before a Senate Armed Service ... more
Photo: Manuel Balce Ceneta / The Associated Press
Senator John Cornyn, Senate Minority Leader Mitch McConnell, R-Ky., and Senator John Barrasso, R-Wyo., listen while Senator Orrin G. Hatch, R-Utah, speaks during a press conference on Capitol Hill Feb. 2, 2011 in Washington, DC. less
Senator John Cornyn, Senate Minority Leader Mitch McConnell, R-Ky., and Senator John Barrasso, R-Wyo., listen while Senator Orrin G. Hatch, R-Utah, speaks during a press conference on Capitol Hill Feb. 2, 2011 ... more
Photo: Brendan Smialowski / Getty Images
Sen. John Cornyn checks his watch before an unusual closed session in the Old Senate Chamber on Capitol Hill in Washington Monday, Dec. 20, 2010.
Photo: Alex Brandon / The Associated Press
Rep. Greg Walden, R-Ore., welcomes Sen. John Cornyn to the stage during the Republican National Congressional Committee's midterm election results watch party at the Grand Hyatt hotel Nov. 2, 2010 in Washington, DC. less
Rep. Greg Walden, R-Ore., welcomes Sen. John Cornyn to the stage during the Republican National Congressional Committee's midterm election results watch party at the Grand Hyatt hotel Nov. 2, 2010 in ... more
Photo: Chip Somodevilla / Getty Images
Sen. John Cornyn during a news conference after taking a tour of the Port of Hidalgo on Friday, Aug. 27, 2010, in Hidalgo, Texas.
Photo: Eric Gay / The Associated Press
Rep. Pete Olson and Sen. John Cornyn listen to Noble Corp.'s Tommy Travis discuss blowout preventers aboard Noble's Danny Adkins rig in the Gulf of Mexico on July 6, 2010.
Photo: Loren Steffy / Houston Chronicle
Noble Corp. division manager Tommy Travis shows pieces of a riser package to Sen. John Cornyn aboard the Noble Danny Adkins rig in the Gulf of Mexico on July 6, 2010.
Rep. Pete Olson and Sen. John Cornyn talk with Noble Corp.'s John Breed aboard Noble's Danny Adkins drilling rig in the Gulf of Mexico on July 6, 2010.
Photo: Houston Chronicle
U.S. Supreme Court nominee, Solicitor General Elena Kagan meets with Sen. John Cornyn on Capitol Hill May 18, 2010 in Washington, DC.
Sen. John Cornyn is seen on Capitol Hill in Washington on April 16, 2010
Flanked by Sen. John Cornyn and Republican leader Mitch McConnell, Sen. Kay Bailey Hutchison speaks during a news conference Wednesday March 31, 2010 in San Antonio.
Photo: JOE MITCHELL / The Associated Press
Sen. John Cornyn looks on as Mitch McConnell, R-Ky., gestures during a news conference on Capitol Hill in Washington, Wednesday, Jan. 20, 2010.
Photo: Pablo Martinez Monsivais / The Associated Press
Sen. John Cornyn speaks during a news conference on Capitol Hill in Washington, Saturday, Dec. 5, 2009.
Photo: Jose Luis Magana / The Associated Press
Senator John Cornyn answers questions from the media outside III Corps headquarters Friday Nov. 6, 2009 on Fort Hood Army Base in Fort Hood, Tx.
Photo: Edward A. Ornelas / San Antonio Express-News
John Cornyn and Kay Bailey Hutchison speak during a press conference outside III Corps headquarters Friday Nov. 6, 2009 on Fort Hood Army Base in Fort Hood, Tx.
John Cornyn listens to Kay Bailey Hutchison speak during a press conference outside III Corps headquarters Friday Nov. 6, 2009 on Fort Hood Army Base in Fort Hood, Tx.
The US flag flies at half-staff as Senator John Cornyn delivers remarks on Nov. 6, 2009 outside US Army III Corps Headquarters one day after the shootings at Fort Hood in Texas.
Photo: Paul J. Richards / AFP/Getty Images
Republican members of the Senate Judiciary Committee, including Sen. John Cornyn, participate in the committee's markup vote on Supreme Court nominee Sonia Sotomayor, Tuesday, July 28, 2009, on Capitol Hill in Washington. less
Republican members of the Senate Judiciary Committee, including Sen. John Cornyn, participate in the committee's markup vote on Supreme Court nominee Sonia Sotomayor, Tuesday, July 28, 2009, on Capitol Hill in ... more
Photo: Susan Walsh / The Associated Press
Supreme Court nominee Sonia Sotomayor talks with Sen. John Cornyn and Sen. Lindsey Graham, R-S.C. on Capitol Hill in Washington, Tuesday July 14, 2009, during a break in her confirmation hearing.
Supreme Court Justice nominee, Sonia Sotomayor meets with Sen. John Cornyn in his office on Capitol Hill June 4, 2009 in Washington, DC.
Photo: Mark Wilson / Getty Images
Senator John Cornyn greets US Army Lieutenant General Benjamin C. Freakley, Commanding General of the US Army Accessions Command, before a hearing on the incidence and prevention of military suicides by the Personnel Subcommittee of the Senate Armed Services Committee in Washington, March 18, 2009. less
Senator John Cornyn greets US Army Lieutenant General Benjamin C. Freakley, Commanding General of the US Army Accessions Command, before a hearing on the incidence and prevention of military suicides by the ... more
Photo: Jonathan Ernst / For the Chronicle
Sen. John Cornyn takes his seat for a hearing on the incidence and prevention of military suicides by the Personnel Subcommittee of the Senate Armed Services Committee in Washington on March 18, 2009.
John Cornyn makes remarks at a hearing on the incidence and prevention of military suicides by the Personnel Subcommittee of the Senate Armed Services Committee in Washington, March 18, 2009.
Brigadier General Frank Turner addresses the media and Army personnel with John Cornyn about the recent trend of suicides in the Battalion and averting future tragedies, at the River Oaks Recruiting Station Friday, Feb. 20, 2009, in Houston. less
Brigadier General Frank Turner addresses the media and Army personnel with John Cornyn about the recent trend of suicides in the Battalion and averting future tragedies, at the River Oaks Recruiting Station ... more
Photo: Johnny Hanson / Houston Chronicle
Sen. John Cornyn talks with reporters after a series of amendment votes on the economic stimulus legislation in the U.S. Capitol Feb. 6, 2009 in Washington, DC.
Despite leading the GOP to a net loss of two seats in last week's election, National Republican Senatorial Committee Chair John Cornyn earned himself a promotion and is poised to take on the roll of minority whip in the upcoming Congress.
In a frank interview with POLITICO, Cornyn ascribed part of the blame to himself and the GOP campaign committee for dropping the ball in an election that looked promising for the Republican Party at the onset. Ultimately, though, he attributed the losses in winnable states, such as Indiana and Missouri, to weak candidates with limited mainstream appeal.
"What is the goal here? I think the goal is to elect principled conservatives in November, not just nominate somebody in the primary that has very little chance of getting elected in November," the Texas senator said. "That doesn't advance the conservative agenda because you have to be elected before you can govern."
After suffering heavy scrutiny in for backing more establishment-oriented candidates in 2010, Cornyn took a more hands-off approach in 2012. Though Republicans picked up seven seats in the midterm election, some of Cornyn's picks were defeated by Tea Party candidates in the primary, rendering both methods marginally unsuccessful.
Cornyn also admitted GOP analysts did a poor job of evaluating the competitiveness of certain races, particularly for the presidency.
"Our side was saying, 'No way, no how, they [Democrats] can replicate 2008,' when in fact they did a pretty good job of doing that in the battleground states," Cornyn said. "So yes, I was surprised. But when I saw Gov. Romney not succeeding in places like Virginia and Pennsylvania, I knew it was going to be a long night."
Cornyn called for members of his party to reconsider whether its worth investing in ideologically pure candidates, such as Missouri Rep. Todd Akin and Indiana Senate candidate Richard Mourdock who both made questionable comments about rape and abortion. He said that philosophy will continue to cost the party seats.
Instead, he said the party needs candidates that are sound both tactically and on policy.
"How can we convey what I believe is the true image, that Republicans actually do care about people of all races, ethnicities, and classes in America?" Cornyn said.
He warned his colleagues that they, too, could face opposition from Tea Party-backed candidates in the 2014 election.
"I told my colleagues in 2012, 'You are going to have a primary, you will have a primary.' And some of them didn't prepare or take it seriously. Some of them did," Cornyn said. "So, I will take my advice and be prepared, and I expect to have one or more primary opponents. Sen. (Mitch) McConnell (R-Kentucky) and everybody up in 2014 will."
Despite the admittedly disappointing results from this election, Cornyn said he sees his nomination for the second highest post in the Senate GOP leadership is reaffirmation of his efforts as chair of NRSC.
""I'm grateful that my colleagues just elected me [minority] whip, which I think is an indication that we did everything humanly possible to achieve a better outcome," he said.
U.S. Politics Video
Latest from the Texas delegation
Live updates from your Congressional delegation

redpajama_set_name: RedPajamaCommonCrawl


text:
Barnyard är ett äventyrsspel som utvecklats av Blue Tongue Entertainment och publicerats av THQ. Spelet är baserat på filmen Bondgård. Det släpptes den 1 augusti 2006 för Nintendo GameCube, PlayStation 2, Game Boy Advance och Windows, och något senare för Wii den 19 november samma år. Spelet går även att spela i mini-game format.

Referenser

Datorspel 2006
Xbox-spel
Game Boy Advance-spel
Nintendo Gamecube-spel
Wii-spel
Playstation 2
Windows-spel


text:
Timing of the initiation of antenatal care: An exploratory qualitative study of women and service providers in East London
Hatherall, B., Morris, Joanne, Jamal, Farah, Sweeney, Lorna, Wiggins, Meg, Kaur, Inderjeet, Renton, Adrian and Harden, A. 2016. Timing of the initiation of antenatal care: An exploratory qualitative study of women and service providers in East London. Midwifery. 36, pp. 1-7.
Hatherall, B., Morris, Joanne, Jamal, Farah, Sweeney, Lorna, Wiggins, Meg, Kaur, Inderjeet, Renton, Adrian and Harden, A.
to explore the factors which influence the timing of the initiation of a package of publically-funded antenatal care for pregnant women living in a diverse urban setting
a qualitative study involving thematic analysis of 21 individual interviews and six focus group discussions.
Newham, a culturally diverse borough in East London, UK
individual interviews were conducted with 21 pregnant and postnatal women and focus group discussions were conducted with a total of 26 health service staff members(midwives and bilingual health advocates) and 32 women from four community groups (Bangladeshi, Somali, Lithuanian and Polish).
initial care-seeking by pregnant women is influenced by the perception that the package of antenatal care offered by the National Health Service is for viable and continuing pregnancies, as well as little perceived urgency in initiating antenatal care. This is particularly true when set against competing responsibilities and commitments in women's lives and for pregnancies with no apparent complications or disconcerting symptoms. Barriers to access to this package of antenatal care include difficulties in navigating the health service and referral system, which are compounded for women unable to speak English, and service provider delays in the processing of referrals. Accessing antenatal care was sometimes equated with relinquishing control, particularly for young women and women for whom language barriers prohibit active engagement with care.
Conclusions and implications for practice
if women are to be encouraged to seek antenatal care from maternity services early in pregnancy, the purpose and value to all women of doing so need to be made clear across the communities in which they live. As a woman may need time to accept her pregnancy and address other priorities in her life before seeking antenatal care, it is crucial that once she does decide to seek such care, access is quick and easy. Difficulties found in navigating the system of referral for antenatal care point to a need for improved access to primary care and a simple and efficient process of direct referral to antenatal care, alongside the delivery of antenatal care which is woman-centred and experienced as empowering.
36, pp. 1-7
Timing of the initiation of antenatal care.pdf
http://dx.doi.org/10.1016/j.midw.2016.02.017
National Institute for Health Research
© 2016 Elsevier. Open Access funded by Department of Health UK. Under a Creative Commons license
The long-term health and wellbeing impacts of Healthy New Towns (HNTs): protocol for a baseline and feasibility study of HNT demonstrator sites in England
Watts, P., Rance, S., McGowan, V., Brown, H., Bambra, C., Findlay, G. and Harden, A. 2020. The long-term health and wellbeing impacts of Healthy New Towns (HNTs): protocol for a baseline and feasibility study of HNT demonstrator sites in England. Pilot and Feasibility Studies. 6 (Art. 4).
Qualitative evidence
Noyes, J., Booth, A., Cargo, M., Flemming, K., Harden, A., Harris, J., Garside, R., Hannes, K., Pantoja, T. and Thomas, J. 2019. Qualitative evidence. in: Higgins, J., Thomas, J., Chandler, J., Cumpston, M., Li, T., Page, M. and Welch, V. (ed.) Cochrane Handbook for Systematic Reviews of Interventions The Cochrane Collaboration.
The long-term health and wellbeing impacts of Healthy New Towns: a six-month feasibility study of Healthy New Town demonstrator sites in England
Harden, A., Rance, S., Watts, P., McGowan, V., Findlay, G., Bambra, C. and Brown, H. 2019. The long-term health and wellbeing impacts of Healthy New Towns: a six-month feasibility study of Healthy New Town demonstrator sites in England. National Institute for Health Research.
How do women with social risk factors experience United Kingdom maternity care? A realist synthesis
Rayment-Jones, H., Sandall, J., Harris, J., Harden, A. and Khan, Z. 2019. How do women with social risk factors experience United Kingdom maternity care? A realist synthesis. Birth. 46 (3), pp. 461-474.
Testing the effectiveness of REACH Pregnancy Circles group antenatal care: protocol for a randomised controlled pilot trial
Wiggins, Meg, Sawtell, Mary, Wiseman, Octavia, McCourt, Christine, Greenberg, Lauren, Hunter, Rachael, Eldridge, Sandra, Haora, P., Kaur, Inderjeet and Harden, A. 2018. Testing the effectiveness of REACH Pregnancy Circles group antenatal care: protocol for a randomised controlled pilot trial. Pilot and Feasibility Studies. 4 (1), p. Art. 169.
Effectiveness and acceptability of myo-inositol nutritional supplement in the prevention of gestational diabetes (EMmY): a protocol for a randomised, placebo-controlled, double-blind pilot trial
Amaefule, Chiamaka Esther, Drymoussi, Zoe, Dodds, Julie, Sweeney, L., Pizzo, Elena, Daru, Jahnavi, Robson, John, Poston, Lucilla, Khalil, Asma, Myers, Jenny, Harden, A., Hitman, Graham A, Khan, Khalid, Zamora, Javier, Huda, Mohammed S B and Thangaratinam, Shakila 2018. Effectiveness and acceptability of myo-inositol nutritional supplement in the prevention of gestational diabetes (EMmY): a protocol for a randomised, placebo-controlled, double-blind pilot trial. BMJ Open. 8 (9), p. e022831.
'It makes sense and it works': maternity care providers' perspectives on the feasibility of a group antenatal care model (Pregnancy Circles)
Hunter, Louise, Da Motta, Giordana, McCourt, Christine, Wiseman, Octavia, Rayment, Juliet, Haora, P., Wiggins, Meg and Harden, A. 2018. 'It makes sense and it works': maternity care providers' perspectives on the feasibility of a group antenatal care model (Pregnancy Circles). Midwifery. 66, pp. 56-63.
Evaluation of community-level interventions to increase early initiation of antenatal care in pregnancy: protocol for the Community REACH study, a cluster randomised controlled trial with integrated process and economic evaluations
Sawtell, Mary, Sweeney, L., Wiggins, Meg, Salisbury, C., Eldridge, Sandra, Greenberg, Lauren, Hunter, Rachael, Kaur, Inderjeet, McCourt, Christine, Hatherall, B., Findlay, G., Morris, Joanne, Reading, Sandra, Renton, A., Adekoya, Ruth, Green, Belinda, Harvey, Belinda, Latham, Sarah, Patel, Kanta, VanLessen, Logan and Harden, A. 2018. Evaluation of community-level interventions to increase early initiation of antenatal care in pregnancy: protocol for the Community REACH study, a cluster randomised controlled trial with integrated process and economic evaluations. Trials. 19 (163).
Cochrane Qualitative and Implementation Methods Group Guidance paper 2: Methods for assessing methodological limitations, data extraction and synthesis, and confidence in synthesized qualitative findings
Noyes, Jane, Booth, Andrew, Flemming, Kate, Garside, Ruth, Harden, A., Lewin, Simon, Pantoja, Tomas, Hannes, Karin, Cargo, Margaret and Thomas, James 2018. Cochrane Qualitative and Implementation Methods Group Guidance paper 2: Methods for assessing methodological limitations, data extraction and synthesis, and confidence in synthesized qualitative findings. Journal of Clinical Epidemiology. 97, pp. 49-58.
Cochrane Qualitative and Implementation Methods Group Guidance Series - paper 1: Introduction
Noyes, Jane, Booth, Andrew, Cargo, Margaret, Flemming, Kate, Garside, Ruth, Hannes, Karin, Harden, A., Harris, Janet, Lewin, Simon, Pantoja, Tomas and Thomas, James 2018. Cochrane Qualitative and Implementation Methods Group Guidance Series - paper 1: Introduction. Journal of Clinical Epidemiology. 97, pp. 35-38.
Cochrane Qualitative and Implementation Methods Group Guidance series - paper 6: Methods for question formulation, searching and protocol development for qualitative evidence synthesis
Harris, Janet L., Booth, Andrew, Cargo, Margaret, Hannes, Karin, Harden, A., Flemming, Kate, Garside, Ruth, Pantoja, Tomas, Thomas, James and Noyes, Jane 2018. Cochrane Qualitative and Implementation Methods Group Guidance series - paper 6: Methods for question formulation, searching and protocol development for qualitative evidence synthesis. Journal of Clinical Epidemiology. 97, pp. 39-48.
Cochrane Qualitative and Implementation Methods Group Guidance Paper 4: Methods for integrating qualitative and implementation evidence within intervention effectiveness reviews
Harden, A., Thomas, James, Cargo, Margaret, Harris, Janet, Pantoja, Tomas, Flemming, Kate, Booth, Andrew, Garside, Ruth, Hannes, Karin and Noyes, Jane 2018. Cochrane Qualitative and Implementation Methods Group Guidance Paper 4: Methods for integrating qualitative and implementation evidence within intervention effectiveness reviews. Journal of Clinical Epidemiology. 97, pp. 70-78.
Better together: A qualitative exploration of women's perceptions and experiences of group antenatal care
Hunter, L. J., Da Motta, G., McCourt, C., Wiseman, O., Rayment, J. L., Haora, P., Wiggins, M. and Harden, A. 2018. Better together: A qualitative exploration of women's perceptions and experiences of group antenatal care. Women and Birth. 32 (4), pp. 336-345.
Cochrane Qualitative and Implementation Methods Group guidance series—paper 3: methods for assessing evidence on intervention implementation
Cargo, M., Harris, J., Pantoja, T., Booth, A., Harden, A., Hannes, K., Thomas, J., Flemming, K., Garside, R. and Noyes, J. 2018. Cochrane Qualitative and Implementation Methods Group guidance series—paper 3: methods for assessing evidence on intervention implementation. Journal of Clinical Epidemiology. 97, pp. 59-69.
Conduct and reporting of acceptability, attitudes, beliefs and experiences of pregnant women in randomised trials on diet and lifestyle interventions: A systematic review
Hamilton, E. Adela A., Nowell, Ann K., Harden, A. and Thangaratinam, Shakila 2018. Conduct and reporting of acceptability, attitudes, beliefs and experiences of pregnant women in randomised trials on diet and lifestyle interventions: A systematic review. European Journal of Obstetrics & Gynecology and Reproductive Biology. 225, pp. 243-254.
"It's my diabetes": Co-production in practice with young people in delivering a 'perfect' care pathway for diabetes
Sharpe, D., Green, Emma, Harden, A., Freer, Rachelle, Moodambail, Abdul and Towndrow, Steven 2018. "It's my diabetes": Co-production in practice with young people in delivering a 'perfect' care pathway for diabetes. Research for All. 2 (2), pp. 289-303.
"Who will marry a diseased girl?": Marriage, gender and tuberculosis stigma in Asia
Hatherall, B., Newell, James N, Emmel, Nick, Baral, Sushil Chandra and Khan, Muhammad Amir 2018. "Who will marry a diseased girl?": Marriage, gender and tuberculosis stigma in Asia. Qualitative Health Research. 29 (8), pp. 1109-1119.
Review 5: Evidence review of barriers to, and facilitators of, community engagement approaches and practices in the UK
Harden, A., Sheridan, K., McKeown, Alex, Dan-Ogosi, I. and Bagnall, Anne-Marie 2016. Review 5: Evidence review of barriers to, and facilitators of, community engagement approaches and practices in the UK. Institute for Health and Human Development, University of East London.
National Institute for Health and Care Excellence Review 4: Community engagement – approaches to improve health: map of the literature on current and emerging community engagement policy and practice in the UK
Bagnall, Anne-Marie, South, Jane, Trigwell, Joanne, Kinsella, Karina, White, Judy and Harden, A. 2016. National Institute for Health and Care Excellence Review 4: Community engagement – approaches to improve health: map of the literature on current and emerging community engagement policy and practice in the UK. Leeds Centre for Health Promotion Research, Leeds Beckett University / Institute for Health and Human Development, University of East London.
In memoriam: the contributions to public health research of Farah Jamal, BA, MSc, PhD
Bonell, Chris, Harden, A., Fletcher, Adam and Viner, Russell 2016. In memoriam: the contributions to public health research of Farah Jamal, BA, MSc, PhD. Journal of Epidemiology and Community Health. 70 (4), pp. 329-330.
Community engagement to reduce inequalities in health: a systematic review, meta-analysis and economic analysis
O'Mara-Eves, A, Brunton, Ginny, McDaid, G, Oliver, Sandy, Kavanagh, Josephine, Jamal, F., Matosevic, T, Harden, A. and Thomas, James 2013. Community engagement to reduce inequalities in health: a systematic review, meta-analysis and economic analysis. Public Health Research. 1 (4).
An economic model of school-based behavioral interventions to prevent sexually transmitted infections
Cooper, Keith, Shepherd, Jonathan, Picot, Jo, Jones, Jeremy, Kavanagh, Josephine, Harden, A., Barnett-Page, Elaine, Clegg, Andrew, Hartwell, Debbie, Frampton, Geoff and Price, Alison 2012. An economic model of school-based behavioral interventions to prevent sexually transmitted infections. International Journal of Technology Assessment in Health Care. 28 (04), pp. 407-414.
The school environment and student health: a systematic review and meta-ethnography of qualitative research
Jamal, F., Fletcher, Adam, Harden, A., Wells, Helene, Thomas, James and Bonell, Chris 2013. The school environment and student health: a systematic review and meta-ethnography of qualitative research. BMC Public Health. 13 (1), p. 798.
Predictors of the timing of initiation of antenatal care in an ethnically diverse urban cohort in the UK
Cresswell, Jenny A, Yu, Ge, Hatherall, B., Morris, Joanne, Jamal, Farah, Harden, A. and Renton, A. 2013. Predictors of the timing of initiation of antenatal care in an ethnically diverse urban cohort in the UK. BMC Pregnancy and Childbirth. 13 (1), p. 103.
Systematic review of the effects of schools and school environment interventions on health: evidence mapping and synthesis
Bonell, C., Farah, Jamal, Harden, A., Wells, H., Parry, W., Fletcher, A., Petticrew, M., Thomas, J., Whitehead, M., Campbell, R., Murphy, S. and Moore, L. 2013. Systematic review of the effects of schools and school environment interventions on health: evidence mapping and synthesis. Public Health Research. 1 (1).
Barriers to the early initiation of antenatal care: a qualitative study of women and service providers in East London
Hatherall, B. 2013. Barriers to the early initiation of antenatal care: a qualitative study of women and service providers in East London. UEL Research and Knowledge Exchange Conference 2013. University of East London, London 26 Jun 2013 London University of East London.
Consulting with young people to inform systematic reviews: an example from a review on the effects of schools on health
Jamal, F. and Harden, A. 2013. Consulting with young people to inform systematic reviews: an example from a review on the effects of schools on health. UEL Research and Knowledge Exchange Conference 2013. University of East London, London 26 Jun 2013 London University of East London.
Getting older and living longer with HIV: Findings from a pilot study conducted in Newham
Foster, Nena, Freeman, Emily, Harden, A., Tobi, Patrick and Fakoya, Ade 2012. Getting older and living longer with HIV: Findings from a pilot study conducted in Newham. UEL Research and Knowledge Exchange Conference 2012. University of East London, London 03 May 2012 London University of East London.
Jamal, Farah, Fletcher, Adam, Harden, A., Wells, Helene, Thomas, James and Bonell, Chris 2013. The school environment and student health: a systematic review and meta-ethnography of qualitative research. BMC Public Health. 13 (1), p. 798.
The contribution of a social enterprise to the building of social capital in a disadvantaged urban area of London
Bertotti, M., Harden, A., Renton, A. and Sheridan, K. 2012. The contribution of a social enterprise to the building of social capital in a disadvantaged urban area of London. Community Development Journal. 47 (2), pp. 168-183.
A scoping review of the evidence relevant to life checks for young people aged 9 to 14 years
Harden, A. 2007. A scoping review of the evidence relevant to life checks for young people aged 9 to 14 years. London EPPI-Centre, Social Science Research Unit, Institute of Education, University of London.
Thematic synthesis
Harden, A. and Thomas, James 2008. Thematic synthesis. ESRC Research Methods Festival. St Catherine's College, Oxford 30 Jun - 03 Jul 2008 Southampton ESRC National Centre for Research Methods.
Testing and building theories: mixed methods synthesis
Harden, A. 2008. Testing and building theories: mixed methods synthesis. ESRC Research Methods Festival. St Catherine's College, Oxford 30 Jun - 03 Jul 2008 Southampton ESRC National Centre for Research Methods.
Critical appraisal and qualitative research: exploring sensitivity analysis
Harden, A. 2008. Critical appraisal and qualitative research: exploring sensitivity analysis. ESRC Research Methods Festival. St Catherine's College, Oxford 30 Jun - 03 Jul 2008
Social and environmental interventions to reduce childhood obesity: a systematic map of reviews
Harden, A. 2008. Social and environmental interventions to reduce childhood obesity: a systematic map of reviews. London EPPI-Centre, Social Science Research Unit, Institute of Education, University of London.
Including diverse groups of children and young people in health promotion and public health research: a review of methodology and practice
Harden, A. 2008. Including diverse groups of children and young people in health promotion and public health research: a review of methodology and practice. London EPPI-Centre, Social Science Research Unit, Institute of Education, University of London.
Health promotion, inequalities and young people's health: a systematic review of research
Harden, A. 2008. Health promotion, inequalities and young people's health: a systematic review of research. London EPPI-Centre, Social Science Research Unit, Institute of Education, University of London.
A review of effectiveness, including cost effectiveness wherever possible, of commissioned healthy weight-related projects in City and Hackney: final report
Harden, A., Estacio, Emee Vida, Tobi, Patrick, Adams-Eaton, Faye, Bertotti, Marcello and Lais, Shahana 2009. A review of effectiveness, including cost effectiveness wherever possible, of commissioned healthy weight-related projects in City and Hackney: final report. London Institute of Health and Human Development, University of East London.
A project to assist Family Actions's Building Bridges practitioners with the use of the Index of Family Relations as an outcome measurement: final report
Harden, A., Lloyd-Reichling, E., Mcdermott, M., Potter, Sylvia and Sayeed, Zahirun 2009. A project to assist Family Actions's Building Bridges practitioners with the use of the Index of Family Relations as an outcome measurement: final report. London University of East London.
Methods for the thematic synthesis of qualitative research in systematic reviews
Thomas, James and Harden, A. 2008. Methods for the thematic synthesis of qualitative research in systematic reviews. BMC Medical Research Methodology. 8 (45), pp. 1471-2288.
The influence of environmental factors on the generalisability of public health research evidence: physical activity as a worked example
Watts, P., Phillips, Gemma, Harden, A. and Renton, A. 2011. The influence of environmental factors on the generalisability of public health research evidence: physical activity as a worked example. International Journal of Behavioural Nutrition and Physical Activity. 8 (1), pp. 1479-5868.
Creating and Maintaining a Healthy Stratford City: Principles and Practices for Success
Sampson, Alice, Harden, A., Brimicombe, A., Bertotti, Marcello, Lais, Shahana, Barrow-Guevera, Gail, Boniwell, Ilona, Joseph, Hipolina, Sheridan, Kevin, Adams-Eaton, Faye, Tobi, Patrick and Li, Yang 2010. Creating and Maintaining a Healthy Stratford City: Principles and Practices for Success. University of East London, Centre for Institutional Studies.
Protocol for a systematic review of the effects of schools and school-environment interventions on health: evidence mapping and syntheses
Harden, A. and Jamal, Farah 2011. Protocol for a systematic review of the effects of schools and school-environment interventions on health: evidence mapping and syntheses. BMC Public Health. 11 (453).
Integrating qualitative research with trials in systematic reviews
Thomas, James, Harden, A., Oakley, Ann, Oliver, Sandy, Sutcliffe, Katy, Rees, Rebecca, Brunton, Ginny and Kavanagh, Josephine 2004. Integrating qualitative research with trials in systematic reviews. British Medical Journal. 328 (7446), pp. 1010-1012.
Applying systematic review methods to studies of people's views: an example from public health research
Harden, A., Garcia, Jo, Oliver, Sandy, Rees, Rebecca, Shepherd, Jonathan, Brunton, Ginny and Oakley, Ann 2004. Applying systematic review methods to studies of people's views: an example from public health research. Journal of Epidemiology and Community Health. 58 (9), pp. 794-800.
A project to assist Family Action's Building Bridges practitioners with the use of the Index of Family Relations as an outcome measurement (Final Report).
Harden, A., Lloyd-Reichling, E., Mcdermott, M., Potter, Sylvia and Sayeed, Zahirun 2009. A project to assist Family Action's Building Bridges practitioners with the use of the Index of Family Relations as an outcome measurement (Final Report). Family Action, Institute of Health and Human Development and CASS School of Education, University of East London.
Teenage pregnancy and social disadvantage: systematic review integrating controlled trials and qualitative studies
Harden, A., Brunton, Ginny, Fletcher, Adam and Oakley, Ann 2009. Teenage pregnancy and social disadvantage: systematic review integrating controlled trials and qualitative studies. British Medical Journal. 339 (121).
Thomas, James and Harden, A. 2008. Methods for the thematic synthesis of qualitative research in systematic reviews. BMC Medical Research Methodology. 8 (45).


Yes it is possible to get more "powerful" batteries, if by powerful you mean batteries with more mAh. The best u can have the bigger number of mAh in a good battery. But it does not stop there, the quality of the charger also matters.
I'd suggest some Powerex 2300mAh(even tho there are 2500mAh from other brands) or maybe you can wait for the next release from Powerex.
For my part, I'd suggest 3 chargers, the Maha C204W, Maha C401FS or the Lightning Pack 4000N; I personally own the C204W and am very pleased with it.
I also have a DSC-W1, and got some Eveready NiMH 2500mAh batteries.
I saw in the ripvan100 article that the Sony BCG34 has no trickle mode, and draws current from batteriesleft in the charger when off or fully charged.
Does the SOny BS-CS2 charger included with the DSC-W1 have the same "flaws"?
I also have a RayOVac PS1 - would this be a better charger for the Evereadys? I think it was primarily designed for lower rating batteries (1200-1600mAh) so I worry that it charges too slowly which I understand is not good for NiMH's.
Too slowly does not mean 4 or 8 hours... If I am not mistaken, it means more like 16 or 24 hours. I'm not sure in how much time your PS1 would charge 2500 mAh batteries since I do not know the current it delivers per hours. You could check it behind your charger. But if its a really old charge, I believe it won't trickle charge, but as long as it is not timer based, it will not damage your cells.
For example, my C204W charger, charges 2 batteries at 2000 mA per hour, so if I put 2 2000mAh batteries, they will be charged within 1 hour. For 4 batteries, it drops to 1000mA per battery per hour, so 2 hours for 2000 mAh batteries. It is not recommended for batteries below 2000mAh, but will charge any batteries above 2000 mAh.
Assuming charging time is roughly mAH rating divided by charging current... :?
2500 mAH / [215 mA +/- 15%] (from 32mA) is about 11.6 (+2/-1.5) hrs. which is way too close to the 12hr termination timer... and this is one battery at a time !
With all 4 installed, it becomes 2500 mAH / [168 mA +/- 18%] (from 30mA) is about 14.9 (+3.2/-2.3) hrs. which is definitely affected by the timer !
So this indicates the PS1 can ONLY properly charge up to 1600-2000 mAH rechargeable batteries...:?